为什么你不应该向JavaScript构造函数添加功能,而是通过原型
Why should you not add functionality to a JavaScript constructor but instead via prototype?
我看看Addy Osmani关于构造函数模式的章节: http://addyosmani.com/resources/essentialjsdesignpatterns/book/#constructorpatternjavascript我遇到了以下内容:
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
this.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
}
// Usage:
// We can create new instances of the car
var civic = new Car( "Honda Civic", 2009, 20000 );
var mondeo = new Car( "Ford Mondeo", 2010, 5000 );
// and then open our browser console to view the
// output of the toString() method being called on
// these objects
console.log( civic.toString() );
console.log( mondeo.toString() );
他说,对于this.toString函数来说,这不是一件好事,因为它不是很理想,并且不会在汽车类型的所有实例之间共享。但他没有解释这到底意味着什么,以及为什么这是一件坏事。他建议执行以下操作:
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
}
// Note here that we are using Object.prototype.newMethod rather than
// Object.prototype so as to avoid redefining the prototype object
Car.prototype.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
// Usage:
var civic = new Car( "Honda Civic", 2009, 20000 );
var mondeo = new Car( "Ford Mondeo", 2010, 5000 );
console.log( civic.toString() );
console.log( mondeo.toString() );
有人可以解释为什么使用原型对象添加此功能是最佳/更好的吗?
原型对象上的函数(更一般地说,属性)由所有实例共享。无论创建多少个"Car"实例,单个"toString"函数都将保持为一个单独的对象。在构造函数中执行赋值时,将为每个函数对象创建一个新的函数对象。
显然,如果每个实例都需要一个可能与其他实例不同的属性,则需要一个每个实例的属性。
当函数位于构造函数内部时,将为"类"的每个新实例创建它。因此,您创建的每个Car
对象都有自己的toString
函数占用额外的内存。
如果通过原型添加toString
,则它只会存在一次,并且您创建的每个Car
对象都将使用相同的函数。
它还整理构造函数代码,使其仅包含与创建对象相关的内容。
原型上的函数在每个实例之间共享。这意味着对于每个实例,这是完全相同的功能,而不是相同的副本。
如果在构造函数中定义函数,则每个实例都必须创建自己的函数版本,然后自己拥有它。这意味着如果您有 100 个实例,则内存中有 100 个函数副本。这也意味着更新函数一点也不好玩,您必须在每个实例上都这样做。
如果函数在原型中,在原型中更新它意味着每个实例现在都使用更新的代码(因为它们都使用相同的共享函数)
例如:
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
}
Car.prototype.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
var civic = new Car( "Honda Civic", 2009, 20000 );
console.log( civic.toString() );
Car.prototype.toString = function () {
return this.model + " has done " + (this.miles * 1.60934) + " kilometers";
};
console.log( civic.toString() );
请注意,我不需要更改civic
实例,它使用新代码并以公里为单位显示距离。
对我来说,一个典型的经验法则是在构造函数中设置特定于给定实例的属性,例如名称、颜色等,并定义"类"应作为原型上的函数共享的函数。
在原型上定义函数与在构造函数上定义函数也存在性能后果。当你在构造函数上定义一个函数时,每次使用构造函数时,你都会一次又一次地重新定义这个函数......
http://jsperf.com/prototype-vs-instance-functions
您不希望在原型上出现类似name
的东西,因为如果您进入并更改Car.prototype.name
,那么您将更改所有新实例的名称 Car
。
希望对您有所帮助!
运行new Car
JS解析器都会在构造函数中执行代码,这意味着您正在创建另一个
this.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
使用prototype
方法,始终只有一个副本toString()
。
- 需要原型内部或外部的功能
- JS添加到功能而不是替换为原型
- Javascript-经理是一个人,但不是经理本身?功能/原型继承
- 功能原型节点不工作
- (功能)原型究竟是如何工作的
- Javascript库扩展了原型功能
- 从原型功能访问原型值
- 为什么你不应该向JavaScript构造函数添加功能,而是通过原型
- 为什么功能原型在这个小提琴里不起作用
- 意外的令牌''在向原型添加功能时
- 有关原型功能的问题
- 了解功能.原型.应用.
- 在功能中更改原型
- JQuery原型功能
- 向Javascript原型添加方法和向现有对象添加功能之间的区别是什么?
- 使用原型添加功能
- 将功能放入对象和原型化它们之间的区别
- 没有找到原型-功能
- 为什么原型功能不会影响控制台.log
- 克隆原型功能保持范围