javascript中关键字“new”的含义

时间:2014-04-08 09:33:32

标签: javascript object

我已经阅读了关于" new" javascript中的关键字(What is the 'new' keyword in JavaScript?)。但是,我还在迷雾中;让我们来谈谈这个例子:

var foo = function() {
    return {
        setA: function(a) {
            this.a = a;
        },
        readA: function() {
            console.log(this.a);
        }
    };
};

现在关于这两段代码的内容是什么:

一:

var bob1 = foo();
bob1.setA(10);
bob1.readA();

二:

var bob2 = new foo();
bob2.setA(10);
bob2.readA();

我看不出任何差异。那么使用关键字" new"会有什么好处? ?

3 个答案:

答案 0 :(得分:4)

如果函数直接返回对象,则不需要new运算符。 new键的功能不止于此。

让我们说

function Animal(kind, name) {
   this.kind = kind;
   this.name = name;
}

Animal.prototype.walk = function() {
    console.log('Walking');
}

然后你正在做

 var animal = new Animal();

Javascript引擎将执行以下操作

  var o = Object.create(Animal.prototype)
  Animal.apply(o, arguments);
  return o;

Object.create将执行prototype函数的Animal对象的原型继承。所以animal对象将拥有自己的属性及其继承属性。

答案 1 :(得分:3)

  

我仍然处于关于new的迷雾中;让我们来谈谈这个例子:

var foo = function() {
    return {
        setA: function(a) {
            this.a = a;
        },
        readA: function() {
            console.log(this.a);
        }
    };
};

我们不应该谈论这个例子。我们是否将new与此函数一起使用并没有什么不同,因为the way new works

  
      
  1. 创建一个新对象,继承自foo.prototype
  2.   
  3. 使用指定的参数和this bound to调用构造函数foo   新创建的对象。
  4.   
  5. 构造函数返回的对象成为结果   整个新表达。如果构造函数不起作用   显式返回一个对象,使用在步骤1中创建的对象   代替。 (通常情况下,施工人员不会返回值,但他们可以   如果他们想要覆盖正常的对象创建,请选择这样做   过程。)
  6.   

第3步是这里要看的东西。您正在创建并返回一个对象(对象文字),因此将被分配给bob1。通常,构造函数不会return任何东西,并且在step1中隐式创建的新实例(在函数内可用this)成为结果。

new foo()foo()都只会将您的对象文字分配给bob变量 - 结果没有区别。 new创建的实例完全被代码忽略。在以下示例中会有所不同:

function foo() {
    this.setA = function(a) {
        this.a = a;
    };
    this.readA = function() {
        console.log(this.a);
    };
    // return this; is implicit
}
var bob = new foo; // OK
var bob = foo(); // horrible error

答案 2 :(得分:1)

如果构造函数foo返回一个对象,那么new foo()与直接调用函数foo()相同。我们可以通过检查ECMAScript behavior for new

来证明这一点
  

返回在构造函数 [即构造函数]上调用[[Construct]]内部方法的结果......

函数的[[Construct]] internal method是一个特殊的包装器,用于调用函数的[[Call]]内部方法(这只是函数的正常行为)。让我们看看[[Construct]]的结尾,看看这个包装器的行为:

  

8)让结果成为调用F [由new] 调用的函数的[[Call]]内部属性的结果,提供< em> obj 作为this值并将参数列表作为args提供给[[Construct]]。

     

9)如果Type( result )是Object,则返回 result

     

10)返回 obj

在您的情况下,构造函数foo返回一个对象,因此[[Construct]]的步骤9(因此,new foo())返回该对象。但是我们在步骤10中看到[[Construct]] 可以返回一些名为 obj 的其他值,它等于构造函数中的this值。让我们回过头来看看这是什么:

  

1)让 obj 成为新创建的本机ECMAScript对象。

     

...

     

4)让 proto 成为使用参数“prototype”调用F的[[Get]]内部属性的值。

     

5)如果Type( proto )是Object,则将 obj 的[[Prototype]]内部属性设置为 proto

这里我们看到了new的真正威力:如果构造函数没有返回一个对象(因此[[Construct]]启动的new操作被允许返回obj }),然后发生原型继承。 [[Prototype]]的{​​{1}}(a.k.a。obj)设置为构造函数方法的obj.__proto__属性。这意味着,如果prototype未返回对象(而是修改foo),并且设置了this,那么从foo.prototype.someProp返回的实例将有权访问{ {1}}。

因此,编写代码的另一种方法可能是:

var instance = new foo()

在这种情况下,instance.someProp会生成一个对象,其原型链包含var foo = function() { }; foo.prototype.setA = function(a) { this.a = a; }; foo.prototype.setA = function(a) { console.log(this.a); }; ,而new foo()则不会。这有利于降低内存使用:这里的所有foo.prototype实例共享通用的原型方法,而不是让每个实例都带有自己独立的函数。