JavaScript中的'new'关键字是什么?

JavaScript中的new关键字在第一次遇到时可能会相当混乱,因为人们倾向于认为JavaScript不是面向对象的编程语言。

  • 它是什么?
  • 它解决了什么问题?
  • 什么时候适合,什么时候不适合?

  • 它有5件事:

  • 它创建一个新的对象。 这个对象的类型只是对象。
  • 它将这个新对象的内部不可访问的[[prototype]](即__proto__ )属性设置为构造函数的外部可访问原型对象(每个函数对象都自动具有原型属性)。
  • 它使this变量指向新创建的对象。
  • 它执行的构造函数,使用每当新创建的对象this被提及。
  • 它返回新创建的对象,除非构造函数返回非null对象引用。 在这种情况下,返回该对象引用。
  • 注意:构造函数引用new关键字之后的函数,如

    new ConstructorFunction(arg1, arg2)
    

    完成此操作后,如果请求了新对象的未定义属性,则该脚本将检查该属性的对象的[[prototype]]对象。 这就是你如何获得类似JavaScript中传统类继承的东西。

    关于这一点最困难的部分是第2点。每个对象(包括函数)都有这个内部属性,称为[[prototype]]。 它只能在对象创建时设置,或者使用new,使用Object.create,或者基于文字(函数默认为Function.prototype,数字为Number.prototype等)。 它只能用Object.getPrototypeOf(someObject)读取。 没有其他方法来设置或读取此值。

    函数除了隐藏的[[prototype]]属性外,还有一个名为prototype的属性,您可以访问和修改这些属性,为您创建的对象提供继承的属性和方法。


    这里是一个例子:

    ObjMaker = function() {this.a = 'first';};
    // ObjMaker is just a function, there's nothing special about it that makes 
    // it a constructor.
    
    ObjMaker.prototype.b = 'second';
    // like all functions, ObjMaker has an accessible prototype property that 
    // we can alter. I just added a property called 'b' to it. Like 
    // all objects, ObjMaker also has an inaccessible [[prototype]] property
    // that we can't do anything with
    
    obj1 = new ObjMaker();
    // 3 things just happened.
    // A new, empty object was created called obj1.  At first obj1 was the same
    // as {}. The [[prototype]] property of obj1 was then set to the current
    // object value of the ObjMaker.prototype (if ObjMaker.prototype is later
    // assigned a new object value, obj1's [[prototype]] will not change, but you
    // can alter the properties of ObjMaker.prototype to add to both the
    // prototype and [[prototype]]). The ObjMaker function was executed, with
    // obj1 in place of this... so obj1.a was set to 'first'.
    
    obj1.a;
    // returns 'first'
    obj1.b;
    // obj1 doesn't have a property called 'b', so JavaScript checks 
    // its [[prototype]]. Its [[prototype]] is the same as ObjMaker.prototype
    // ObjMaker.prototype has a property called 'b' with value 'second'
    // returns 'second'
    

    这就像类继承,因为现在,使用new ObjMaker()创建的任何对象也将继承“b”属性。

    如果你想要一个类似于子类的东西,那么你可以这样做:

    SubObjMaker = function () {};
    SubObjMaker.prototype = new ObjMaker(); // note: this pattern is deprecated!
    // Because we used 'new', the [[prototype]] property of SubObjMaker.prototype
    // is now set to the object value of ObjMaker.prototype.
    // The modern way to do this is with Object.create(), which was added in ECMAScript 5:
    // SubObjMaker.prototype = Object.create(ObjMaker.prototype);
    
    SubObjMaker.prototype.c = 'third';  
    obj2 = new SubObjMaker();
    // [[prototype]] property of obj2 is now set to SubObjMaker.prototype
    // Remember that the [[prototype]] property of SubObjMaker.prototype
    // is ObjMaker.prototype. So now obj2 has a prototype chain!
    // obj2 ---> SubObjMaker.prototype ---> ObjMaker.prototype
    
    obj2.c;
    // returns 'third', from SubObjMaker.prototype
    
    obj2.b;
    // returns 'second', from ObjMaker.prototype
    
    obj2.a;
    // returns 'first', from SubObjMaker.prototype, because SubObjMaker.prototype 
    // was created with the ObjMaker function, which assigned a for us
    

    在最终找到这个页面之前,我阅读了大量有关这个主题的垃圾,在这个页面中,这很好地解释了这一点。


    假设你有这个功能:

    var Foo = function(){
      this.A = 1;
      this.B = 2;
    };
    

    如果您将其作为独立函数调用,如下所示:

    Foo();
    

    执行此函数将向window对象( AB )添加两个属性。 它把它添加到window ,因为window是当你执行它像调用该函数的对象,而this在一个函数调用函数的对象。 至少在Javascript中。

    现在,用new名称来称呼它:

    var bar = new Foo();
    

    当你给函数调用添加new时候会发生什么?一个新的对象被创建(只是var bar = new Object() ),并且this函数内的这个Object指向你刚创建的新Object ,而不是被调用的对象功能。 所以bar现在是属性AB的对象。 任何函数都可以是构造函数,但它并不总是合理的。


    除了霍华德的回答之外,这里是new (或者至少似乎是这样做的):

    function New(func) {
        var res = {};
        if (func.prototype !== null) {
            res.__proto__ = func.prototype;
        }
        var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
        if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
            return ret;
        }
        return res;
    }
    

    var obj = New(A, 1, 2);
    

    相当于

    var obj = new A(1, 2);
    
    链接地址: http://www.djcxy.com/p/1067.html

    上一篇: What is the 'new' keyword in JavaScript?

    下一篇: What is the scope of variables in JavaScript?