什么是原型
js中的原型指的是一个对象可以从另一个对象继承特性。每个对象都有一个原型对象,对象以其原型对象为模板,继承其属性,方法。原型对象也有自己的原型对象,这样一层一层,通常称为原型链。
准确来说,这些属性和方法,定义在对象的构造函数(constructor functions)之上的prototype属性上面,而不是对象实例本身。
js中链接对象实例和原型的是_proto_,它是从构造函数的prototype派生的,之后上溯到原型链,在构造器中找到这些属性和方法。
js中不是所有的对象都可以作为原型对象,每个对象都是继承自Object,但是我们主动设置一个对象的原型为另一个对象。
prototype属性
继承的属性和方法被定义在prototype属性上,prototype属性的值是一个对象。
constructor属性
每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数。
构造函数,原型,实例之间的关系
下面我们将通过一些例子来看一下
//构造函数1
function Person( name,age ){
this.name = name;
this.age = age;
};
//构造函数2
function Test (){
}
//实例1
var person1 = new Person("小明", 21);
//原型链为: person1 ====> Person ====> Object ====> null
console.log(person1.constructor);
/*output:
person1.constructor指向构造函数Person
ƒ Person(name, age) {
this.name = name;
this.age = age;
}
*/
console.log(person1.__proto__);
console.log(Person.prototype);
/*output:
{
constructor: ƒ Person(name, age)
__proto__: Object
}
*/
console.log(person1.__proto__ === Person.prototype); //true
//实例2;
var person2 = new Test();
//把实例person1作为person2的原型
person2.__proto__ = person1;
//原型链为: person2 ====> person1 ===> Person ===> Object ====>null
console.log(person2.name) //小明,继承自person1
console.log(person2.constructor);
/*output:
ƒ Person(name, age) {
this.name = name;
this.age = age;
}
*/
console.log(person2.__proto__);
/*output:
{
Person
age: 21
name: "小明"
__proto__:
{
constructor: ƒ Person(name, age)
__proto__: Object
}
}
*/
console.log(person2.__proto__.__proto__ === Person.prototype); //true
//实例3
//create() 实际做的是从指定原型对象创建一个新的对象。这里以 person1 为原型对象创建了 person3 对象。
var person3 = Object.create(person1);
//原型链为: person3 ====> person1 ===> Person ===> Object ====>null
console.log(person3.__proto__);
/*output:
{
Person
age: 21
name: "小明"
__proto__:
{
constructor: ƒ Person(name, age)
__proto__: Object
}
}
*/
不改变对象的原型链继承另一个对象的方法
//构造函数1
function Person( name,age ){
this.name = name;
this.age = age;
};
//构造函数2
function Test (){
}
//方法一:
var person4 = new Test();
//用call或者apply来改变this,在person4的作用域里面去执行Person
//Person.call(person4);
Person.apply(person4);
console.log(person4.__proto__);
/*
constructor: ƒ Test()
__proto__: Object
*/
//方法二: 可以直接在构造函数里面使用apply或者call
//比如:
function Test (){
Person.call(this);
}
四个拓展原型链的方法
new操作符做了什么事情
//new 的过程
var obj = new Object(); //创建一个新对象
obj.__proto__ = A.prototype; //让obj的__proto__指向A.prototype
A.call(obj) //在obj的作用环境执行构造函数的代码,使this指向obj
return obj //返回实例对象