向原型添加函数 vs 对象字面量(使用 this)
Adding function to prototype vs object literal (using this)
我知道,如果我将一个函数添加到构造函数原型中,那么使用该构造函数的每个对象都可以使用该函数。而且我知道,如果您将函数添加为(我认为它被称为对象文字?),您将必须将其作为构造函数本身的 属性 来访问。 (Difference between adding function to prototype and object literal in javascript).
但是,如果您在构造函数中将新函数声明为 'this.xxx()' 会怎么样。这与在原型上声明 属性 有什么不同?
我的猜测是,在原型上声明函数对象会导致委托(并且该函数只会存在一个副本)。与 'this' 相比,每个构造的对象都会有自己的函数副本。
对吗?
function A () {
}
A.prototype.printNum = function () {
console.log('hi');
}
x = new A ();
x.printNum(); // hi
function B () {
this.printNum = function () {
console.log('hi');
}
}
y = new B ();
y.printNum(); // hi
不同的是当你调用构造函数(使用new
)你执行里面的东西,所以,如果你添加声明一堆时间new B()
你会遇到性能问题。
您的直觉是正确的,通过检查函数引用是否相同很容易自己检查。只需将这些行添加到您的示例代码中:
var x2 = new A();
var y2 = new B();
y.printNum === y2.printNum; //will return false
x.printNum === x2.printNum; //will return true
所以确实,当函数在原型上时,两个实例对象将共享引用。 (因为当 printNum
属性 查找在 x
和 x2
上失败时,它将被委托给相同的原型对象,A.prototype
。如果 y
和y2
,两个实例都有一个自己的printNum
属性,所以原型链甚至都没有被查询。)
(顺便说一句,对象字面量是一个几乎不相关的主题,请参阅 MDN 了解它的定义。)
你是对的。
function A() {}
A.prototype.printNum = function() {};
function B() {
this.printNum = function() {};
}
var a1 = new A();
var a2 = new A();
console.log(a1.printNum == a2.printNum); // true
var b1 = new B();
var b2 = new B();
console.log(b1.printNum == b2.printNum); // false
在第一种情况下,函数实现有一个实例printNum
。在第二种情况下,B
的每个实例都有自己的函数 printNum
.
拥有许多函数会占用更多内存并且对象创建成本更高,但原型查找也会成为性能问题(根据某些人的说法,我仍然更喜欢它们)。
还有一个区别:很多库使用object.hasOwnProperty()
来判断一个属性是否是"is part of"一个对象。 object.hasOwnProperty()
returns true
如果 属性 是在对象本身上定义的而不是被继承的。
var a = new A();
cosole.log(a.hasOwnProperty('printNum')); // false
var b = new B();
console.log(b.hasOwnProperty('printNum')); // true
例如,JSON.stringify
使用它来检查哪些属性应包含在其输出中。这并不重要,因为我们正在谈论函数(JSON.stringify
将忽略它),但让我们使用这个例子:
function C() {}
C.prototype.myvar = "Hello world!";
function D() { this.myvar = "Hello world!"; }
var c = new C();
var d = new D();
console.log(JSON.stringify(c)); // {}
console.log(JSON.stringify(d)); // {"myvar":"Hello world!"}
在 ES5 之前,在 JavaScript 中创建变量 "final" (Java) / "readonly" (C#) 是相当困难的。第二种方法允许这样做:
function C(finalVariable) {
this.getMyVariable = function() { return finalVariable };
}
我并不是说这是好的风格或者应该在实践中使用(它甚至不安全,因为 getMyVariable
也可能被覆盖),这只是一个事实:使用这个函数实例化允许从构造函数访问变量,而不通过对象属性将它们暴露给其他函数。
我知道,如果我将一个函数添加到构造函数原型中,那么使用该构造函数的每个对象都可以使用该函数。而且我知道,如果您将函数添加为(我认为它被称为对象文字?),您将必须将其作为构造函数本身的 属性 来访问。 (Difference between adding function to prototype and object literal in javascript).
但是,如果您在构造函数中将新函数声明为 'this.xxx()' 会怎么样。这与在原型上声明 属性 有什么不同?
我的猜测是,在原型上声明函数对象会导致委托(并且该函数只会存在一个副本)。与 'this' 相比,每个构造的对象都会有自己的函数副本。
对吗?
function A () {
}
A.prototype.printNum = function () {
console.log('hi');
}
x = new A ();
x.printNum(); // hi
function B () {
this.printNum = function () {
console.log('hi');
}
}
y = new B ();
y.printNum(); // hi
不同的是当你调用构造函数(使用new
)你执行里面的东西,所以,如果你添加声明一堆时间new B()
你会遇到性能问题。
您的直觉是正确的,通过检查函数引用是否相同很容易自己检查。只需将这些行添加到您的示例代码中:
var x2 = new A();
var y2 = new B();
y.printNum === y2.printNum; //will return false
x.printNum === x2.printNum; //will return true
所以确实,当函数在原型上时,两个实例对象将共享引用。 (因为当 printNum
属性 查找在 x
和 x2
上失败时,它将被委托给相同的原型对象,A.prototype
。如果 y
和y2
,两个实例都有一个自己的printNum
属性,所以原型链甚至都没有被查询。)
(顺便说一句,对象字面量是一个几乎不相关的主题,请参阅 MDN 了解它的定义。)
你是对的。
function A() {}
A.prototype.printNum = function() {};
function B() {
this.printNum = function() {};
}
var a1 = new A();
var a2 = new A();
console.log(a1.printNum == a2.printNum); // true
var b1 = new B();
var b2 = new B();
console.log(b1.printNum == b2.printNum); // false
在第一种情况下,函数实现有一个实例printNum
。在第二种情况下,B
的每个实例都有自己的函数 printNum
.
拥有许多函数会占用更多内存并且对象创建成本更高,但原型查找也会成为性能问题(根据某些人的说法,我仍然更喜欢它们)。
还有一个区别:很多库使用object.hasOwnProperty()
来判断一个属性是否是"is part of"一个对象。 object.hasOwnProperty()
returns true
如果 属性 是在对象本身上定义的而不是被继承的。
var a = new A();
cosole.log(a.hasOwnProperty('printNum')); // false
var b = new B();
console.log(b.hasOwnProperty('printNum')); // true
例如,JSON.stringify
使用它来检查哪些属性应包含在其输出中。这并不重要,因为我们正在谈论函数(JSON.stringify
将忽略它),但让我们使用这个例子:
function C() {}
C.prototype.myvar = "Hello world!";
function D() { this.myvar = "Hello world!"; }
var c = new C();
var d = new D();
console.log(JSON.stringify(c)); // {}
console.log(JSON.stringify(d)); // {"myvar":"Hello world!"}
在 ES5 之前,在 JavaScript 中创建变量 "final" (Java) / "readonly" (C#) 是相当困难的。第二种方法允许这样做:
function C(finalVariable) {
this.getMyVariable = function() { return finalVariable };
}
我并不是说这是好的风格或者应该在实践中使用(它甚至不安全,因为 getMyVariable
也可能被覆盖),这只是一个事实:使用这个函数实例化允许从构造函数访问变量,而不通过对象属性将它们暴露给其他函数。