js继承的几种方式
1 原型链继承
2 构造函数继承
3 深拷贝 浅拷贝
4 ES5的object.create()
5 apply call 继承
1 原型链继承
var a={ name :"a", sex:"男", run:function(){ console.log(this.name) } } var b={ name:"b" }
b.__proto__ = a
b.name // b
b.sex//男
b.run()//b
如上代码所示
当b.name如果能在b对象中找到name属性则停止,
b.sex查找sex属性时 当前对象中没有找到sex属性则去原型链上查找,查找b的隐式原型(__proto__),发现b的隐式原型被我们人为的指向了a(本来是指向Object.prototype) 继而查找到a的sex属性,返回 "男"
2 构造函数继承
构造函数继承从某种意义上来说 也是原型链继承。我们先看代码
//构造函数a function a(){ this.name="a", this.run=function(){ console.log(this.name) } }
a.prototype={
sex:"男",
walk:function(){
console.log(this.sex)
}
}
//生成对象 b var b=new a(); b.name//a b.sex//"男 b.run()//"a"
b.walk()//"男"
我们看上面的代码 通过构造函数生成的b对象
可以看到 b对象中拥有name 和 run属性
b对象的__proto指向的构造函数 a的prototype 所以达到了继承的效果 但是具体的实现逻辑是怎样的呢
问题回到了 我们通过构造函数a生成b对象的时候具体做了什么,也就是这行代码
//生成对象 b var b=new a();
构造函数生成对象时做了四步
1.生成了个空对象 b //var b ={}
2.将构造函数a的的隐式原型指向了a的prototype(跟第一种继承方法的原型链继承一致) // b.__proto__=a.prototype
3 通过 apply call将b的上下文环境置为a的上下文环境 //a.apply(b)
4 返回 对象 //return b
注:当构造函数里包含返回语句时情况比较特殊, 构造函数可以包含返回语句(不推荐),但返回值必须是this,或者其它非对象类型的值(这个有兴趣的可以自己研究下,这里我们不做深入讨论)
3 深拷贝 浅拷贝
浅拷贝就是指对象间的循环赋值,来看代码
var a={ name:"a", age:[1,2,3] } var b; for(var i in a){ b[i]=a[i] } b.name//"a" b.age//[1,2,3]
但是浅拷贝有个明显的问题,我们来看,我现在改变a对象的age属性现在再看b对象 的age
也相应的改变了
所以浅拷贝的对象赋值的时候只是复制了对象的内存地址,当a对象改变了其属性的内存地址时候,b对象相应属性的值也改变了。所以我们可以用深拷贝来解决这个问题
var a={ name:"a", age:[1,2,3] } var b={ name:"b", age:[1,2], kid:{ name:‘kid‘, age:[3,4] } } function extend(parent){ if(parent instanceof Array) var b=[] else var b={} for(var i in parent){ if(typeof parent[i]==="object"){ b[i]=extend(parent[i]) }else{ b[i]=parent[i] } } return b } var c=extend(a) var d=extend(b)
输出结果为
初步看起来拷贝成功了,现在我们改变 a的age属性的值可以看到a.age已经被改变了
我们再看c.age
没有被影响,所以说深拷贝成功了
4 object.create()
我查阅mdn上得解释为The Object.create()
method creates a new object with the specified prototype object and properties.return A new object with the specified prototype object and properties.
意思是创建一个具有指定原型且可选择性地包含指定属性的对象 返回一个具有指定的内部原型且包含指定的属性(如果有)的新对象。
其实Object.create()方法的底层也是原型链继承 来看列子
var a={ name:"a", sex:"男", run:function(){ console.log(this.name) } } var b=Object.create(a) b.name //a b.age //男 b.run() //a
5 apply call
这个比较简单,意思是通过appl call动态改变上下文来达到继承的目的
function a(){ this.name="a", this.sex="男", this.run=function(){ console.log(this.name) } } var b; a.apply(b) b.name//a b.sex//男 b.run//a
也能达到继承的问题
原文:http://www.cnblogs.com/absonAlex/p/6344682.html