关于原型,原型链,继承的几种方法
创建对象的几种方式:
//字面量
var a = {name:'zhangsan'}
var b = new Object({name:'lisi'})
//构造函数
var M = function(name){
this.name = name
}
var c = new M('wangwu)
//Object对象创建
var d = {name:'xiaoliu'}
var e = Object.create(d)
有上图可以看出构造函数new 出来的实例对象,有一个__proto__的指针。指向构造函数的原型对象。然后与构造函数的原型对象发生链条关系,就出现了原型链。下面我们打印出来如下的关系:
也就是说M new出来的实例对象--->M构造函数的prototype原型对象。M构造函数的原型对象中有constructor构造器,这个属性指向构造函数自己本身。
c instanceof M // true 用instanceof来检测c 是不是构造函数New 出来的实例对象。
下面就几种继承的方式,比较一下优缺点。
1,通过构造函数的方式继承
function Father(){
this.name = 'zhangsan'
}
Father.prototype.say = function(){
console.log('我是father的原型方法')
}
function Son(){
Father.call(this)
this.age = 18
}
var a = new Son()
var b = new Father()
console.log(b.say) // function(){console.log('我是father的原型方法')}
console.log(a) // Son {name:'zhangsan',age:18}
console.log(a.say) //undefiend
有call继承Father的实例对象。
缺点就是:无法继承原型下的属性或者方法。
2.通过原型链继承
function Father() {
this.name = 'zhangsan'
this.arr = [1,2,3]
}
function Son(){
this.age = 18;
}
Son.prototype = new Father()
console.log(new Son)
var a = new Son()
var b = new Son()
a.arr.push(4)
console.log(a.arr) //[1,2,3,4]
console.log(b.arr) //[1,2,3,4]
有上面代码看出,通过此种方法实现继承是有缺点的,
实例化两个Son 的实例对象,如果在父类中有引用类型的属性,会被共享,意思就是一个改动,全部改动。
3,组合继承
//3混合继承
function Father() {
this.name = 'zhangsan'
this.arr = [1,2,3]
}
function Son(){
Father.call(this)
this.age = 18
}
Son.prototype = new Father()
var a =new Son()
var b =new Son()
a.arr.push(4)
console.log(a.arr,b.arr) //[1,2,3,4] [1,2,3]
//虽然通过这种方式继承解决了被共享的问题,但是出现了下面的问题。在实例化Son时候,调用了父级的构造函数2次。
4,组合继承的另外一种写法
function Father() {
this.name = 'zhangsan'
this.arr = [1,2,3]
}
function Son(){
Father.call(this)
this.age = 18
}
Son.prototype = Father.prototype
var a =new Son()
var b =new Son()
a.arr.push(4)
console.log(a.arr,b.arr) //[1,2,3,4] [1,2,3]
这样写虽然解决了调用父级构造函数两次的问题,但是有这样的一个问题,就是子元素new 出来的是实例对象的 指向不明确,不知道是父级里的还是子元素里面的。
5 最优的继承方法
function Father() {
this.name = 'zhangsan'
this.arr = [1,2,3]
}
function Son(){
Father.call(this)
this.age = 18
}
Son.prototype = Object.create(Father.prototype)
Son.prototype.constructor = Son
var a =new Son()
var b =new Son()
a.arr.push(4)
console.log(a.arr,b.arr) //[1,2,3,4] [1,2,3]
解决了子元素的实例对象的constructor 指向不明的问题。
以上就是个人对原型,原型链,继承的理解。