浅谈Javascript的new运算符

1、背景app

在网上看到一篇别人转的玉伯前辈关于“new FunctionName()运行机制浅析”的文章,里面举了一个例子,代码以下:函数

 

function Dog(name) {
    this.name = name;
    Dog.prototype = {
        shout: function() { alert("I am " + this.name); }
    };
}
var dog1 = new Dog("Dog 1");
dog1.shout();

 

 

运行以后报错:Uncaught TypeError: Object #<Dog> has no method 'shout'this

实际上,new Dog()的过程等价于spa

var o = {__proto__: Dog.prototype};
Dog.apply(o);
return o;

而JS引擎在遇到函数声明的时候会给函数对象添加prototype属性,即Dog.prototype = {constructor: Dog},运行到new Dog(...)时,prototype

执行的操做至关于code

// Dog.prototype = {constructor: Dog};
var o = {__proto__: Dog.prototype};
// 如今,o = {__proto__: {constructor: Dog}}
Dog.apply(o);
// 如今,Dog.prototype = {shout: function(){...}}
return o;

因此,dog1.shout()会报错也是情理之中的事情。对象

 

2、探索blog

虽然dog1没有shout()方法,可是目前Dog的prototype已是{shout: function(){...}}继承

因此此时再写2句var dog2 = new Dog('xxx');dog2.shout();就能够正常执行了原型

总的来讲,上面的构造函数还都是比较规范的,下面咱们作一点改变,在构造函数里加一句return 语句

function a() {
    this.name = 'joe';
    return {name: 'ray'};
}
var obj = new a();
alert(obj.name);    //ray

运行的结果是ray,因而可知,new a()生成的a对象被抛弃,返回的是return语句后面的对象

下面咱们再来作一个实验

function a() {
    this.name = 'joe';
    return 'ray';
}
var obj = new a();
alert(obj.name);    //joe
alert(obj);         //[object Object]

这回obj.name的值是joe,并且obj是一个对象,说明new a()生成的a对象并无被抛弃

 

3、小结

    事实上,在使用new Func()来生成一个对象的时候, 整个过程是这样的:

    一、建立一个新对象,它的类型是Func,而且它会继承Func.prototype的全部属性(原型继承)

    二、构造函数被调用,this对象被绑定给这个新建立的对象

    三、若构造函数没有明确的返回值,那么新建立的对象就是整个 new 表达式的结果;反之,若构造函数内显式定义了返回值,则该返回值为整个 new 表达式的结果

相关文章
相关标签/搜索