我对js原型链的理解
2016-04-26 02:55
633 查看
引言
从关键字 new 说起
__proto__与prototype
Function与Object
结尾
js原型链是js面向对象编程的基础和重点,许多文章都对它进行了讲解,这里我想谈谈我对原型链的理解,一方面加深自己的印象,另一方面希望能和大家分享交流。
我来试着模拟一下new的操作过程。
来测试一下
结果如下
结果与new关键字生成的对象一致。
稍微总结一下,new关键字的行为与后面的方法是不是 Object() 有关,
在 非Object() 方法时,执行下面四步
这里我把
对象访问属性的顺序是先查找自身,显然 hobby 和 swim 都不是obj自身的属性,这是系统会查找
根据我的研究,函数的prototype属性的初始化很简单,分为两步
因为People.prototype是一个普通的object对象,所以有
这与图中的描述是吻合的。
如此一来,下面的原型链就形成了
obj −→−−−−−−− __proto__ People.prototype −→−−−−−−− __proto__ Object.prototype−→−−−−−−− __proto__ null
有一条对原型链文章的评价:js对象其实就是键值对,说的不错,js中的方法和变量都以对象的形式存在,一个对象能访问到的其实就是 自己的属性 和 原型链上的属性。
看看下面的例子
发现结果仍然是
我们再做进一步测试
这一步解释了原型对象中的方法是怎么被执行的。
![](http://laruence-wordpress.stor.sinaapp.com/uploads/javascript_object_layout.jpg)
这个图解释了原型链的原理,放在这里供大家参考
js中所有的对象都是由函数通过new操作符生成的,比如
则一定有
而所有的函数对象都是由 Function() 函数生成的,Object()方法也不例外,所以有
当然,Function()方法也是由自己生成的,所以推出
(其实Object()方法和Function()方法都是 本地代码(native code),也就是事先写好的,并不是生成的对象,原型链中这样设计是为了逻辑的完备)。
这里比较特殊的两个对象是 function.prototype 和 object.prototype,这两个对象的生成不符合上面提到的规律
function.prototype 作为Function的原型对象是由Function()函数直接返回的,并不是一个object对象,而且这个属性是只读的,它的值显示如下
从逻辑上来说, 所有的函数对象也应该能访问 Object.prototype 的属性,所以有
让所有的函数对象通过 function.prototype 访问原型链的末端 Object.prototype。
作为原型链的尾端, Object.prototype 的属性可以被js中的所有对象访问, Object.prototype 的
从关键字 new 说起
__proto__与prototype
Function与Object
结尾
引言 |
从关键字 new 说起 |
//模拟new关键字的行为 function methodNew( func ) //func:新对象的构造函数 { if ( func === Object ) return Object(); //Object()方法返回原始的object对象 else { var obj = {}; //{}实际上等价于Object() obj.constructor = func; //更改obj的constructor属性 obj.__proto__ = func.prototype; //设置obj.__proto__属性,从而访问到原型链上的属性, //比如 func.prototype.name可以通过 obj.name读取,但是不能使用obj.name来修改,这样会为obj添加一个name属性。 //这里只处理func方法参数为空的情况 func.call( obj ); //为obj添加func方法中定义的属性,比如 //function func(){ this.name = "Jerry" } //相当于执行obj.name = "Jerry" return obj; } }
来测试一下
function People() { this.name = "杨幂"; this.introduce = function() { alert("My name is "+ this.name ); } } var obj = methodNew( Object ); var beauty = methodNew( People ); console.log( obj ); console.log( beauty );
结果如下
Object {} People {constructor: function, name: "杨幂", introduce: function}
结果与new关键字生成的对象一致。
稍微总结一下,new关键字的行为与后面的方法是不是 Object() 有关,
在 非Object() 方法时,执行下面四步
1. var obj = {}; //生成一个object对象 2. obj.constructor = func; //设置constructor,由此判断对象的类型由constructor属性决定 3. obj.__proto__ = func.prototype; //这一步很关键,将obj连入原型链,从而能访问func.prototype对象以及它的原型链上端对象的属性 4. func.call( obj ); //为obj添加func()方法中声明的属性
__proto__
与prototype
这里我把__proto__放在前面,因为它是原型链的基础。
People.prototype.hobby = "篮球"; People.prototype.swim = function(){ console.log( "swimming" ) }; var obj = {}; obj.__proto__ = People.prototype; console.log( obj.hobby ); obj.swim;
对象访问属性的顺序是先查找自身,显然 hobby 和 swim 都不是obj自身的属性,这是系统会查找
obj.__proto__指向的对象是否有这两个属性,这里就是 People.prototype ,如果还没有,会继续找
People.prototype.__proto__指向的对象有没有所需属性,这里有一个知识点,声明一个函数People()时,People.prototype 属性指向谁呢?
根据我的研究,函数的prototype属性的初始化很简单,分为两步
1. People.prototype = {}; //将一个object对象赋给prototype 2. People.prototype.constructor = People; //设置constructor为People,表示原型对象的类型是People
因为People.prototype是一个普通的object对象,所以有
People.prototype.__proto__指向 Object.prototype ,
这与图中的描述是吻合的。
如此一来,下面的原型链就形成了
obj −→−−−−−−− __proto__ People.prototype −→−−−−−−− __proto__ Object.prototype−→−−−−−−− __proto__ null
有一条对原型链文章的评价:js对象其实就是键值对,说的不错,js中的方法和变量都以对象的形式存在,一个对象能访问到的其实就是 自己的属性 和 原型链上的属性。
看看下面的例子
People.prototype.hobby = "篮球"; People.prototype.swim = function(){ console.log( "swimming" ) }; var obj = {}; obj.__proto__ = People.prototype; //console.log( obj.hobby ); //obj.swim; obj.hobby = "撩妹"; console.log( People.prototype.hobby );
发现结果仍然是
篮球,说明这里是为obj添加了自己的hobby属性,并没有改动原型对象的属性。
我们再做进一步测试
People.prototype.sing = function(){ console.log( this.song ) } var obj = {}; obj.song = "爱的供养"; obj.__proto__ = People.prototype; obj.sing(); People.prototype.sing.call( obj ); //结果 //爱的供养*2
这一步解释了原型对象中的方法是怎么被执行的。
![](http://laruence-wordpress.stor.sinaapp.com/uploads/javascript_object_layout.jpg)
这个图解释了原型链的原理,放在这里供大家参考
Function与Object
图中 Function 与 Object 的关系比较令人费解,其实可以这么理解。js中所有的对象都是由函数通过new操作符生成的,比如
var obj = new People()
则一定有
obj.__proto__ == People.prototype'
而所有的函数对象都是由 Function() 函数生成的,Object()方法也不例外,所以有
Object.__proto__ = Function.prototype
当然,Function()方法也是由自己生成的,所以推出
Function.__proto__ = Function.prototype
(其实Object()方法和Function()方法都是 本地代码(native code),也就是事先写好的,并不是生成的对象,原型链中这样设计是为了逻辑的完备)。
这里比较特殊的两个对象是 function.prototype 和 object.prototype,这两个对象的生成不符合上面提到的规律
1. People.prototype = {}; 2. People.prototype.constructor = People;
function.prototype 作为Function的原型对象是由Function()函数直接返回的,并不是一个object对象,而且这个属性是只读的,它的值显示如下
function Empty() {}
从逻辑上来说, 所有的函数对象也应该能访问 Object.prototype 的属性,所以有
function.protototype.__proto__ = Object.prototype
让所有的函数对象通过 function.prototype 访问原型链的末端 Object.prototype。
作为原型链的尾端, Object.prototype 的属性可以被js中的所有对象访问, Object.prototype 的
__proto__是只读的,这保证了 Object.prototype 作为原型链的一个出口。
结尾
希望能对读者朋友们有所启发,有想法请留言与我交流,转载请注明作者和地址,谢谢!相关文章推荐
- JS跨域调用之document.domain--相同基础域名页面之间的调用
- Javascript的replace函数以及PHP中的str_replace()函数
- javaScript基础
- [置顶] javascript入门基础小案例-----按键盘的方向键来控制块的移动z注释:
- JS字符串与对象互相转换
- JSON格式化
- rails提供跳转js的ajax实例分析特殊情况
- JavaScript事件处理的方式(三种)
- js 求时间差的实现代码
- js计算时间差代码【包括计算,天,时,分,秒】
- js获取页面及个元素高度、宽度的代码
- 深入理解JS中的substr和substring
- javascript锚点
- javaScript中parseFloat()结果精度不一致的问题
- js闭包
- 如何用js判断一个复选框是否被选中
- ServletContext JSP
- 常用原生JS方法总结(兼容性写法)
- json文件转excel表格
- 从服务器获取数据,引入组件