JavaScript-原型链和继承-3

function Son() {
    this.name = 'a';
    this.names = ['a'];
}
var son1 = new Son();
son1.name = 'b';
son1.names.push('b');
var son2 = new Son();
console.log(son2.name); //a
console.log(son2.names); //a

可以看出,实例属性是副本

function Son() {

}
Son.prototype.name='a';
Son.prototype.names=['a'];
var son1 = new Son();
son1.name = 'b';
son1.names.push('b');
var son2 = new Son();
console.log(son2.name); //a
console.log(son2.names); //a,b

这里把name和names改成原型属性,发现原型属性中基本类型name是副本,而引用类型names的值变化了。

那么在不知道是否是基本类型的属性还是引用类型的属性,只记住实例属性是不变化的。

我们可以这么操作

再试试函数

function Son() {
    this.print = function() {
        console.log('a');
    }
}
var son1 = new Son();
son1.print = function() {
    console.log('b');
}
var son2 = new Son();
son2.print();//a
function Son() {}
Son.prototype.print = function() {
    console.log('a');
}
var son1 = new Son();
son1.print = function() {
    console.log('b');
}
var son2 = new Son();
son2.print();//a

说明方法互不影响。

再试试原型继承

function Father(){
  this.name='a';
  this.names=['a'];

}
function Son(){
}
Son.prototype=new Father();
var son1=new Son();
var son2=new Son();
son1.name='b';
son1.names.push('b');
console.log(son2.name);//a
console.log(son2.names);//a,b
var father=new Father();
console.log(father.name);//a
console.log(father.names);//a
//子类之间互相影响
function Father() {}
Father.prototype.name = 'a';
Father.prototype.names = ['a'];

function Son() {}
Son.prototype = new Father();
var son1 = new Son();
var son2 = new Son();
son1.name = 'b';
son1.names.push('b');
//var son2 = new Son();//将声明放在属性修改之后,结果仍旧一样
console.log(son2.name); //a
console.log(son2.names); //a,b
var father = new Father();
console.log(father.name); //a
console.log(father.names); //a,b
//说明子类还能修改了父类的原型属性中的引用属性
function Father() {
    this.print = function() {
        console.log('a');
    }
}
function Son() {}
Son.prototype = new Father();
var son1 = new Son();
var son2 = new Son();
son1.print = function() {
    console.log('b');
}
son2.print();//a
var father = new Father();
father.print();//a
function Father() {}
Father.prototype.print = function() {
    console.log('a');
}
function Son() {}
Son.prototype = new Father();
var son1 = new Son();
var son2 = new Son();
son1.print = function() {
    console.log('b');
}
son2.print(); //a
var father = new Father();
father.print(); //a

这么看来,原型链继承方式,构造函数的实例属性是独立的。其它的会互相影响。在无法区份到底是基本数据类型还是引用类型,只考虑实例属性的稳定性。方法则互不影响。

1.子类的原型属性中的引用类型互相影响,Son.prototype.names=['a']

2.子类从父类继承来的实例属性中的引用属性会互相影响

组合模式中,子类从父类继承的属性是实例属性。

组合继承中,父类(超类)的属性必须是实例属性,才能在call或者apply中进行调用。而方法则无所谓。我们试一下方法放在构造函数中,看能否继承和修改。

function Father() {
    this.print = function() {
        console.log('a');
    }
}
function Son() {
    Father.call(this);
}
Son.prototype = new Father();
var son1 = new Son();
var son2 = new Son();
son1.print(); //a
son1.print = function() {
    console.log('b');
}
son1.print(); //b
son2.print(); ///a
var father = new Father();
father.print(); //a

再尝试一下

function Father() {}
Father.prototype.print = function() {
    console.log('a');
}

function Son() {
    Father.call(this);
}
Son.prototype = new Father();
var son1 = new Son();
var son2 = new Son();
son1.print(); //a
son1.print = function() {
    console.log('b');
}
son1.print(); //b
son2.print(); ///a
var father = new Father();
father.print(); //a

我们现在看一下Son.prototype.constructor = Son这个到底做了什么。

function Son() {}
console.log(Son === Son.prototype.constructor); //true
function Father() {};
Son.prototype = new Father();
console.log(Son === Son.prototype.constructor); //false

 可以看到,原型继承的过程中,constructor不在指向原有的构造函数。

那么试试构造函数继承

function Father() {};

function Son() {
    Father.apply(this);
}
console.log(Son === Son.prototype.constructor); //true

不受影响

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值