在讲原型之前先补点知识。。。。
构造函数的注意事项
- 默认函数首字母大写。
- 构造函数并没有显示返回任何东西,当调用构造函数时,new会自动创建this对象,且类型就是构造函数类型。
- 因为构造函数也是函数,所以可以直接调用,但是它的返回值是undefine,此时构造函数里面的this对象等于全局this对象。
原型
- 构造函数中有一个属性:
prototype
,叫原型,是给我们程序员用的。 - 实例对象中有一个属性:
__proto__
,也叫原型,这个是给浏览器看的。 - 构造函数中的原型和实例对象中的原型都是属性,也都是对象。
- 构造函数中的
prototype
和实例中的__proto__
指向相同。 -
prototype
的数据可以被实例对象访问和使用。 - 如果希望数据能够共享,应该把数据放在原型中写属性和方法,如果不需要共享,那就放在构造函数中定义。
- 实例对象调用的方法,如果在构造函数的
prototype
中存在就可以直接被调用
例子:
//构造函数
function Person(name, age) {
this.name = name;
this.age = age;
this.eat = function () {
console.log("今天晚上我要吃鸡腿");
};
}
//实例对象
var p = new Person("小黑", 12);
console.dir(p.__proto__);
console.dir(Person.prototype);
console.dir(p);
console.dir(Person);
/*
*
* 构造函数中都有一个属性:prototype,叫原型,是程序员用的
* 实例对象中都有一个属性:`__proto__`,叫原型,是浏览器用的,不标准
* 无论是`prototype`还是`__proto__`都可以看成是一个对象
*
* 构造函数中的原型(prototype)和实例对象中的原型`__proto__`都是属性,也都是对象
* 构造函数中的prototype和实例对象中的`__proto__`指向相同
* */
//构造函数中只有属性
function Person(name, age) {
this.name = name;
this.age = age;
}
//在Person的原型中添加eat方法
Person.prototype.eat = function () {
console.log("有了");
};
var p1 = new Person("小黑", 20);
var p2 = new Person("小白", 21);
//实例对象是可以使用的
p1.eat();
p2.eat();
console.dir(p1);
console.dir(p2);
console.dir(Person);
console.log(p1.eat === p2.eat);//true
原型链
- 构造函数和实例对象是通过原型联系的。
- 原型链的指向是可以改变的
- 如果实例对象中的属性和原型对象中的属性重名,使用实例对象中的属性,但是原型对象中的属性不会改变。
- 对象中的
__proto__
指向的是自己的构造函数的prototype
. - 如果构造函数的
prototype
指向发生改变,那么实例对象中的__proto__
指向也会发生改变。 - 如果实例对象的原型指向改变了,在向原型中添加方法,那么这个方法添加到了所改变指向的位置。