// 一、构造函数
function Person(name) {
this.name = name;
};
// 二、Es6 class
class Person2 {
constructor(name) {
this.name = name;
};
};
复制代码
// 实例化
console.log(new Person('张三'), new Person2('李四'));
复制代码
function Parent1() {
this.name = 'parent1';
};
Parent1.prototype.say = function() { // 没法被Child1的实例对象继承
console.log('say hello!');
};
function Child1() {
Parent1.call(this); // 改变this指向
this.type = 'child1';
};
console.log(new Child1());
复制代码
PS:缺点是只能继承构造函数中的属性和方法,没法继续原型对象上的属性和方法,如图: bash
function Parent2() {
this.name = 'parent2';
};
Parent2.prototype.say = function() {
console.log('say hello parent2!');
};
function Child2() {
this.type = 'child2';
};
Child2.prototype = new Parent2();
console.log(new Child2()) // new Child2()_proto_===Child2.prototype
复制代码
继承的原理:new Child2()实例对象的_proto属性指向的是构造函数Child2的prototype原型对象,
即 new Child2()_proto_===Child2.prototype;
因为Child2.prototype = new Parent2(),
则可经过 new Parent2()的_proto_属性找到Parent2的prototype原型对象。
复制代码
PS:缺点是经过一个构造函数实例多个对象时候,修改构造函数的属性,全部的继承自构造函数的实例对象的改属性都将改变。以下所示:函数
function Parent2() {
this.name = 'parent2';
this.arr1 = [1,2,3,4];
this.arr2 = [1,2,3,4];
};
function Child2() {
this.type = 'child2';
};
Child2.prototype = new Parent2();
var obj1 = new Child2();
var obj2 = new Child2();
obj1.arr1.push(5) // 因为obj自己并无arr1属性,则经过_proto_原型链找到了Parent2的arr2属性
obj1.arr2 = [1,2,3,4,5] // 这种方式并不会修改obj2.arr2属性,至关于给obj1新增长了arr2属性。
console.log(obj1, obj2)
复制代码
obj1.arr1.push(5)
修改使得
obj2.arr1
的值也被修改。这显然不是咱们想要的,咱们但愿各个实例之间是相互独立的。
function Parent3() {
this.name = 'parent3';
this.arr1 = [1,2,3,4];
};
Parent3.prototype.say = function() {
console.log('say hello!')
}
function Child3() {
Parent3.call(this); // 改变了this指向,使得Parent3中的this指向的是Child3的实例对象。
this.type = 'child3';
};
Child3.prototype = new Parent3()
var o3 = new Child3();
var o4 = new Child3();
o3.arr1.push(5)
console.log(o3, o4)
复制代码
Parent3
构造函数被执行了两次。
Parent3.call(this); // 改变了this指向,使得Parent3中的this指向的是Child3的实例对象。
Child3.prototype = new Parent3() // 既然上面已经继承了Parent3构造函数中的属性,这里只是为了继承Parent3原型属性
思考:根据以前原型链的相关知识,有如下关系
new Parent3().__proto__ === Parent3.prototype
故这里能够改为:
Child3.prototype = Parent3.prototype // 缺点Child3和Parent3的constructor是同一个
复制代码
var o3 = new Child3(); // 这里o3实例应该是由`Child3`直接生成的实例。
更具根据以前原型链的相关知识
o3 instanceof Child3 // true
o3 instanceof Parent3 // true
instanceof判断o3是Child3原型链上的一个实例若是想要直接判断o3是Child3直接生成的实例,能够经过constructor:
咱们指望
o3.constructor === Child3
三实际上的结果:
o3.constructor === Parent3
复制代码
// 代码优化
function Parent4() {
this.name = 'parent4';
this.arr1 = [1,2,3,4];
};
function Child4() {
Parent3.call(this);
this.type = 'child4';
};
Child4.prototype = Object.create(Parent4.prototype); // Object.create建立的对象只是_proto_的引用
Child4.prototype.constructor = Child4 // 给Child4原型对象添加constructor,覆盖_proto_的constructor
var o5 = new Child4();
var o6 = new Child4();
o5.arr1.push(5)
console.log(o5, o6)
复制代码
instanceo
和constructor
的使用。