将函数连接到原型与否之间的差异
Differences Between Hooking a Function onto Prototype or Not
之间有什么区别
function Gandalf() {
this.color = 'grey';
}
Gandalf.prototype.comeBack = function() {
this.color = 'white';
}
和:
function Gandalf() {
this.color = 'grey';
this.comeBack = function() {
this.color = 'white';
return this;
};
}
在什么情况下,我应该将方法挂接到原型上,或者不挂?
好吧,Kay探员,我会用不同于Esailija的方式来处理这个问题。让我们从简单的对象开始。例如,假设您已经有一个名为gandalf
:的对象
var gandalf = {
color: "grey",
comeBack: function () {
this.color = "white";
return this;
}
};
此代码中没有构造函数。因此,此代码易于理解。我是对的还是对的?
好吧,现在我要做一些很棒的事情。我将从gandalf
:创建radagast
var radagast = Object.create(gandalf);
radagast.color = "brown";
这里发生了什么?让我们把它分解:
- 我们使用
Object.create
从gandalf
创建了一个名为radagast
的新对象。因此CCD_ 7继承自CCD_ - 我们将
radagast
的color
设置为棕色,而不是灰色
更简单地说,想象一下你和我进行了以下对话:
I: Hey Agent Kay, I met Radagast yesterday.
U: Who's Radagast?
I: Hmm... do you know who's Gandalf?
U: Yes, I do.
I: Well Radagast is just like Gandalf except that he's brown instead of white.
这正是继承在JavaScript中的工作方式。您可以看到JavaScript具有原型继承。在原型继承中,对象从其他对象继承。在这种情况下,radagast
继承自gandalf
。
现在,他们通常在JavaScript中实现原型继承的方式很奇怪。我称之为原型继承的构造函数模式。例如,以您的代码:
function Gandalf() {
this.color = "grey";
}
Gandalf.prototype.comeBack = function() {
this.color = "white";
return this;
};
现在,当您创建Gandalf
的实例时,该实例从哪个对象继承?它继承自Gandalf.prototype
:
var gandalf = new Gandalf;
alert(Object.getPrototypeOf(gandalf) === Gandalf.prototype); // true
当你说new Gandalf
是时会发生什么
var gandalf = Object.create(Gandalf.prototype);
Gandalf.call(gandalf);
如果你扩展Gandalf.call(gandalf)
,你会得到:
var gandalf = Object.create(Gandalf.prototype);
gandalf.color = "grey";
现在举第二个例子:
function Gandalf() {
this.color = "grey";
this.comeBack = function() {
this.color = "white";
return this;
};
}
在这种情况下,当您创建Gandalf
的实例时,实际上是在执行以下操作:
var gandalf = Object.create(Gandalf.prototype);
gandalf.color = "grey";
gandalf.comeBack = function () {
this.color = "white";
return this;
};
因此,每次创建新的Gandalf
时,都会创建一个新的函数comeBack
。因此,如果你调用new Gandalf
10次,你也会有10个不同的comeBack
函数。
与第一个例子相比,因为comeBack
是在Gandalf.prototype
上定义的,所以每次调用new Gandalf
时,我们都会得到一个继承自Gandalf.prototype
的新对象。因此,只有一个comeBack
函数在Gandalf
的所有实例之间共享。这不是更好吗?
从本质上来说,你的第一个例子是这样的:
var gandalfPrototype = {
create: function () {
var gandalf = Object.create(this);
gandalf.color = "grey";
return gandalf;
},
comeBack: function () {
this.color = "white";
return this;
}
};
var gandalf = gandalfPrototype.create(); // there's only one comeBack function
类似地,你的第二个例子相当于这个:
var gandalfPrototype = {
create: function () {
var gandalf = Object.create(this);
gandalf.color = "grey";
gandalf.comeBack = function () {
this.color = "white";
return this;
};
return gandalf;
}
};
var gandalf = gandalfPrototype.create(); // there's 1 comeBack for each instance
请记住,在函数调用之前使用new
时,实际上是从函数的prototype
继承的。而不是函数本身。
最后,我想说(因为我是J.R.R.托尔金的忠实粉丝),这就是我写代码的方式:
var wizard = {
create: function (color) {
var wizard = Object.create(this);
wizard.color = color;
return wizard;
}
};
var gandalf = wizard.create("grey");
gandalf.comeBack = function () {
this.color = "white";
return this;
};
var saruman = wizard.create("white");
var radagast = wizard.create("brown");
谢谢你阅读我的答案。
之所以将其放在原型上,是因为创建的每个对象都可以使用相同的函数对象(函数只是可调用的对象),它们只需要不同的标识和数据。但在第二种情况下,您将为每个对象创建唯一的函数对象,即使它们可以使用相同的函数对象。
既然你似乎了解PHP,那么在PHP中的区别是相似的:
class Gandalf {
public $color = "grey";
public function comeBack() {
$this->color = "white";
}
}
class Gandalf {
public $color = "grey";
//Create the method inside constructor everytime
public function __construct() {
$this->comeBack = function() {
$this->color = "white";
return $this;
}->bindTo($this, $this);
}
}
当性能不受关注时,很难说何时使用另一个。就我个人而言构造函数的模糊和额外的缩进级别足以让我更喜欢原型。
要回答:
在什么情况下,我应该将方法挂接到原型上,或者不挂?
如果您有一个函数需要访问使用构造函数创建的对象的私有vars
,那么它需要位于构造函数内部。
function Gandalf() {
var age = '30000'; //approximate
this.alertAge1 = function() {
alert( age );
};
}
Gandalf.prototype.alertAge2 = function() {
// age not visible from here
};
- 函数参数中的数据与指定变量之间的任何性能差异
- JavaScript中的函数和对象之间没有区别吗?
- Jquery在函数之间传递表行
- d3中堆栈函数和嵌套函数之间的差异
- javascript函数的:和=之间的区别
- 函数中this和var之间的区别
- 如何在函数之间切换
- JavaScript/jQuery-添加添加和删除类与下一个函数之间的延迟
- Javascript-defineProperty和直接在对象上定义函数之间的区别
- 函数声明与函数表达式之间的性能差异
- 函数()和新函数()之间的区别
- MeteorJS-函数()和()之间的差异=>
- JavaScript函数,用于计算两个日期之间的年、月和天数
- 在Jquery调用之间添加其他函数
- 在函数之间传递javascript变量
- 两个函数之间的角度承诺
- 命名一个在“”和“”之间切换元素的函数;启用”;以及“;被禁用”;州
- 如何在异步函数与Deferredjquery之间同步
- 如何创建一个确定2个数字之间值的函数
- Javascript创建函数,以便在其他函数之间共享变量