构造函数
这里我们主要讲构造函数的封装特性 用构造函数实例创建的对象彼此独立,互不影响。
function Dog(name, type, age, bark) {
this.name = name;
this.type = type;
this.age = age;
this.bark = function () {
console.log("爱叫");
};
}
let dog = new Dog("大黄", "土狗", 5);
console.log(dog);
dog.bark();
这段代码也很好的体现了构造函数的初始化对象的成员变量。
但是构造函数其实是存在一个浪费内存的问题。
怎么解决这个浪费内存的问题呢?这就要在原型中找到答案了。
原型
构造函数通过原型分配的函数是所有对象所共享的
JavaScript规定,每一个构造函数都有一个prototype属性,指向另一个对象,也称为原型对象。
这个对象可以挂载函数,对象实例化不会多次创建原型上的函数,节约内存
我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法。
构造函数和原型对象 中的this都指向实例化对象。
每一个原型对象里面又有一个constructor属性,该属性指向该原型对象的构造函数。
对象里面又都有一个_proto_属性指向构造函数的prototype原型对象,可以看下图,之所以我们对象可以使用构造函数原型对象的属性和方法,就是因为他的存在
原型继承:因为构造函数的属性和方法共享,当我们都使用他的时候是可以继承的,但是因为他们使用的都是同一个对象,根据引用类型的特点,他们都指向同一个对象,修改一个就会都影响。
解决方法:构造函数,因为构造函数new每次都会创建一个新的对象。
function Person() {
this.eyes = 2;
this.head = 1;
}
// console.log(new Person)
// 女人 构造函数 继承 想要 继承 Person
function Woman() {}
// Woman 通过原型来继承 Person
// 父构造函数(父类) 子构造函数(子类)
// 子类的原型 = new 父类
Woman.prototype = new Person(); // {eyes: 2, head: 1}
// 指回原来的构造函数
Woman.prototype.constructor = Woman;
// 给女人添加一个方法 生孩子
Woman.prototype.bbay = function () {
console.log("宝贝");
};
const red = new Woman();
console.log(red);
// console.log(Woman.prototype)
// 男人 构造函数 继承 想要 继承 Person
function Man() {}
// 通过 原型继承 Person
Man.prototype = new Person();
Man.prototype.constructor = Man;
const pink = new Man();
console.log(pink);
原型链
说简单点,原型链就是因为原型对象之间的相互关联形成的一个链。看下图,前面说过每一个原型对象prototype都有一个对象原型_proto_。
原型链的查找规则
实在不好理解的话你可以记住这两个点:
所有的对象里面都有 __proto__ 对象原型 指向构造函数的原型对象
所有的原型对象里面有 constructor, 指向 创造该原型对象的构造函数