何时使用“原型”一词向 javascript 中的对象添加新属性
When to use the word "prototype" in adding new properties to an object in javascript?
我不明白在JavaScript中何时使用"原型"一词,还是使用简单的"点"符号而不使用"原型"一词。有人可以查看这些代码块并帮助我了解何时要使用一个而不是另一个吗?
使用"原型":
function employee(name,jobtitle)
{
this.name=name;
this.jobtitle=jobtitle;
}
var fred=new employee("Fred Flintstone","Caveman");
employee.prototype.salary=null;
fred.salary=20000;
console.log(fred.salary);
没有"原型":
function employee(name,jobtitle,salary)
{
this.name=name;
this.jobtitle=jobtitle;
this.salary=salary;
}
var fred=new employee("Fred Flintstone","Caveman", 20000);
console.log(fred.salary);
JavaScript 对象有一个属性,该属性是指向另一个对象的指针。此指针是对象的原型。默认情况下,对象实例共享相同的原型:
function Employee(name){
this.name = name;
}
Employee.prototype.company = "IBM";
Employee.prototype.who = function(){
console.log("My name is", this.name, "I work for", this.company);
}
var bob = new Employee('Bob');
var jim = new Employee('Jim');
// bob and jim are seperate objects, but each is linked to the same 'prototype' object.
jim.who(); // jim doesn't have a property called 'who', so it falls back to it's 'prototype', where who exists
// My name is Jim I work for IBM
bob.who();
// My name is Bob I work for IBM
// Bob leaves IBM for Microsoft
bob.company = "Microsoft"; // bob now has a property called 'company'. The value of which is 'Microsoft', which overrides bob's prototype property of the same name.
bob.who();
// My name is Bob I work for Microsoft
Employee.prototype.company = 'Facebook';
jim.who();
// My name is Jim I work for Facebook
bob.who(); // Bob is not affected by the change.
// My name is Bob I work for Microsoft
delete bob.company;
bob.who(); // bob no longer has it's own property 'company', so like jim, it drops down to the prototype object.
// My name is Bob I work for Facebook
围绕JS和继承的问题可能很复杂,但你的问题的答案相对简单。 请考虑以下代码:
function Klass() { }
var obj1 = new Klass();
var obj2 = new Klass();
现在,如果将属性添加到 obj1
,则该属性仅存在于 obj1
上。 同样obj2
.
如果将属性添加到 Klass
,则该属性同样仅存在于 Klass(函数对象(上。 它根本不影响obj1
和obj2
。
但是如果你在Klass.prototype
中添加一个属性,那么该属性将同时存在于obj1
和obj2
上,以及通过new Klass
创建的任何未来对象上。 如果随后更改原型上的属性值,则更改的值将是您在所有这些对象上看到的值。
你可以在Klass
函数的主体中添加代码来向this
添加属性;这将导致任何将来的Klass
对象获得这些属性。 但是每个对象都有自己的副本 - 它可以在内存方面加起来,特别是当属性是方法时 - 并且这些副本不会受到未来对Klass
正文的更改的影响。
ES5 的Object.create
几乎不再需要麻烦.prototype
。
所以,拿@Gerry的例子,你可以像
var Mammal = {
walk: function() {}
};
var Dog = Object.create(Mammal, {
bark: {
value: function() {}
}
}); // create a new object which [[prototype]] refers to Mammal
Dog.walk();
Dog.bark();
prototype
对象有点难以理解;但是这篇关于OOP JavaScript的文章可以帮助阐明一些问题。
简而言之,prototype
对象为"收件人"对象提供了蓝图 - 您所要做的就是将收件人的prototype
属性指向蓝图对象。 请注意,您可以根据需要拥有任意数量的原型蓝图对象的接收者(因此 Car 和 Train 都可以指向一个通用的车辆原型对象(。
您可以自由定义原型对象中的属性和函数,任何接收对象都可以使用,例如:
var vehiclePrototype = {
// A property which will be supplied to the recipient
cost: 0,
// A method which will be supplied the recipient
move: function () {
// Your prototype can refer to 'this' still.
console.log("Moving " + this.name);
};
}
您现在可以创建一个利用vechiclePrototype
的Car
:
// Factory method for creating new car instances.
function createCar(name) {
// Define the Car's constructor function
function Car(name) {
this.name = name;
}
// Point the car's prototype at the vechiclePrototype object
Car.prototype = vechiclePrototype;
// Return a new Car instance
return new Car(name);
}
// Create a car instance and make use of the Prototype's methods and properties
var mustang = createCar(mustang);
mustang.cost = 5000;
mustang.move();
可以以类似的方式创建新的 Train 对象:
function createTrain(whilstleSound) {
// Define the Train's constructor function
function Train(name) {
this.whilstleSound = whilstleSound;
}
// Point the train's prototype at the vechiclePrototype object
Train.prototype = vechiclePrototype;
// Return a new Train instance
return new Train(name);
}
var ic125 = new Train("pooop pooop");
ic125.move();
使用原型继承的一大优点是Car
和Train
的所有实例共享完全相同的move
函数(而不是创建同一函数的多个实例(,如果这些对象的许多实例,这将节省大量内存。
忽略new
,忽略.prototype
它们只是令人困惑的概念。如果你真的想要原型继承,请使用Object.create
但大多数时候继承完全是矫枉过正。(原型继承应仅用作优化技术(。
构建类时,只需创建对象并扩展它们。
var Walker = {
walk: function() {}
}
var Eater = {
eat: function () {}
}
var Dog = extend({}, Eater, Walker, {
bark: function () {},
sniffBehind: function () {}
})
function dog(dogName) {
return extend({}, Dog, {
name: dogName
})
}
var steveTheDog = dog("steve")
console.log(steveTheDog.name === "steve")
使用任意的arity扩展函数,_.extend
,jQuery.extend
,pd.extend
等。
PD实现如下extend
function extend(target) {
[].slice.call(arguments, 1).forEach(function(source) {
Object.getOwnPropertyNames(source).forEach(function (name) {
target[name] = source[name]
})
})
return target
}
使用原型,您可以以"更干净"的方式进行扩展,因为您将构造函数中的逻辑与定义对象的属性和方法分开。
var Mammal = function() { ... };
Mammal.prototype = {
walk: function() { ... }
};
var Dog = function() { ... };
for (var prop in Mammal.prototype) {
Dog.prototype[prop] = Mammal.prototype[prop];
}
Dog.prototype.bark = function() { ... };
但是,上面没有原型的内容可能如下所示:
var Mammal = function() {
this.walk = function() { ... };
};
var Dog = function() {
Mammal.apply(this);
this.bark = function() { ... };
};
然而,这种扩展对象的方式被现代JavaScript库(如Underscore.js(变得无关紧要,或者也可以在jQuery的帮助下编写得更干净。
单词prototype
在整个应用程序中为特定类型(数组、函数、自定义类型的数量(定义一些功能
例如,您可以使用属性 sum
扩展所有数组:
const arrayPrototype = Array.prototype
Object.defineProperty(arrayPrototype, 'sum', {
get() { return this.reduce((a,b) => a + b, 0) }
})
执行代码块后,所有数组都具有以下属性:
console.log([1,3,-1,10].sum) // prints 13
- FabricJs-限制主对象内添加对象的移动区域
- 向Angular作用域对象添加对象数组——TypeError
- Javascript使用+添加对象
- 动态添加对象的jQuery事件处理程序
- 添加JQuery UI在Meteor中添加对象后可调整大小
- 在我的上下文中添加对象的动态方法
- 如何检测是否已使用 angular.forEach AngularJS 添加对象
- 在对象coffeescript中添加对象数组
- 使用Jquery在单击“”时显示表单;添加对象”;按钮
- 我可以向数组添加对象键吗
- 向扩展数组的JS集合添加对象(继承?)
- 尝试通过从自动完成推送添加对象时缺少 $$Hashkey
- 添加对象值 Javascript
- 在上传问题时添加对象
- 如何使用 javascript 的变量名称在数组中添加对象属性
- 在 JavaScript/TypeScript 中动态地“直接”添加对象属性到“this”
- 如何仅当对象不存在时才使用javascript添加对象
- 如何在数组末尾添加对象的副本
- rails在javascript url中添加对象
- ThreeJS-按不同顺序添加对象会影响alpha/显示