我已经阅读了关于" 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"会有什么好处? ?
答案 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:
- 创建一个新对象,继承自
foo.prototype
。- 使用指定的参数和
this
bound to调用构造函数foo
新创建的对象。- 构造函数返回的对象成为结果 整个新表达。如果构造函数不起作用 显式返回一个对象,使用在步骤1中创建的对象 代替。 (通常情况下,施工人员不会返回值,但他们可以 如果他们想要覆盖正常的对象创建,请选择这样做 过程。)
醇>
第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
实例共享通用的原型方法,而不是让每个实例都带有自己独立的函数。