神奇的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操作符的主要内容,如果未能解决你的问题,请参考以下文章

神奇的操作--O快速乘

神奇的位操作

记录一个python里面很神奇的操作,对一个包含列表的元组进行增量赋值,成功赋值但还报错

Python的神奇方法指南

malloc_trim和SetProcessWorkingSetSize两个神奇的内存相关函数

malloc_trim和SetProcessWorkingSetSize两个神奇的内存相关函数