神奇的new操作符
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了神奇的new操作符相关的知识,希望对你有一定的参考价值。
在使用new操作符实例化构造函数的时候,你有没有产生过困惑究竟new操作符帮我们做了什么?接下来我们就来揭开它的神秘面纱,来看一下其内部究竟是怎么运行的。
我们先看一个例子:
function Person(name,age){ this.name=name; this.age=age; } Person.prototype.getPerson=function(){ console.log(this.name+‘的年龄是‘+this.age); };
new实例化,调用getPerson方法,我们得到了‘张三的年龄是13’的结果
var zhangSan=new Person(‘张三‘,‘13‘); zhangSan.getPerson(); //张三的年龄是13
那么这整个过程究竟是怎样的呢?接下来我们就来详细分析一下,首先 new Person(‘张三‘,‘13‘) 实例化的过程:
function new2(func){ //创建一个对象 var newObject={}; //设置原型链 newObject._proto_=func.prototype; //修改this指向新对象newObject,并执行函数体func var result=func.apply(newObject,arguments); //判断函数体的返回类型,如果是引用类型,返回这个引用类型 if(result instanceof Object){ return result; //否则,返回新对象newObject }else{ return newObject; } }
这个过程只是模拟理解,实际上实例对象有一个内部属性[[Prototype]]指向构造函数的原型对象,而脚本中并没有标准的方式访问[[Prototype]],但 Firefox、Safari 和 Chrome 在每个对象上都支持一个属性__proto__;
而在其他实现中,这个属性对脚本则是完全不可见的
有的同学可能会困惑new操作符实例化返回的结果不都是一个新的对象吗?我们来试验一下:
function Person(name,age){ this.name=name; this.age=age; return { ‘aaa‘:‘哈哈哈,我是不是很奇怪‘ } } Person.prototype.getPerson=function(){ console.log(this.name+‘的年龄是‘+this.age); }; console.log(new Person(‘张三‘,‘13‘)); //{‘aaa‘:‘哈哈哈,我是不是很奇怪‘}
上面的结果返回了对象{‘aaa‘:‘哈哈哈,我是不是很奇怪‘},所以一般情况下构造函数不返回任何值。
了解了new操作符内部的工作原理,我们就来看一下zhangSan.getPerson()调用方法的这个过程,细心的同学可以留意到getPerson这个方法我们绑在了构造函数的原型上,而实例化的对象本身并没有这个方法,那么它是怎样调用并得到了我们想要的结果呢?
答案就是我们刚刚分析的new操作符的工作原理,实例化的对象有一个内部属性[[Prototype]],指向构造函数的原型对象,当我们调用某一个方法时:
1.都会先执行第一次搜索:实例化对象本身有无此方法,如果有,则返回实例化对象本身定义的方法调用;
2.如果无,则执行第二次搜索,内部属性[[Prototype]]指向的构造函数的原型对象,如果能找到,则返回原型中的定义的方法调用,如果没有,则会报错。
在本示例中,则是返回了原型中定义的方法调用,得到了‘张三的年龄是13’的结果。
这个过程的模拟代码如下:
function getProperty(obj, prop) { if (obj.hasOwnProperty(prop)) return obj[prop] else if (obj.__proto__ !== null) return getProperty(obj.__proto__, prop) else return undefined }
参考资料:
1.Javascript – How Prototypal Inheritance really works
2.new运算符
以上是关于神奇的new操作符的主要内容,如果未能解决你的问题,请参考以下文章
记录一个python里面很神奇的操作,对一个包含列表的元组进行增量赋值,成功赋值但还报错