Wit*_*tuz 151 javascript extends prototype function object
我目前正在从Java转换为Javascript,我有点难以弄清楚如何按照我希望的方式扩展对象.
我见过互联网上有几个人使用一种名为extend on object的方法.代码如下所示:
var Person = {
name : 'Blank',
age : 22
}
var Robot = Person.extend({
name : 'Robo',
age : 4
)}
var robot = new Robot();
alert(robot.name); //Should return 'Robo'
Run Code Online (Sandbox Code Playgroud)
有谁知道如何使这项工作?我听说你需要写
Object.prototype.extend = function(...);
Run Code Online (Sandbox Code Playgroud)
但我不知道如何使这个系统工作.如果不可能,请告诉我另一个扩展对象的替代方案.
osa*_*oun 191
编辑:
在使用代码之前,请检查user2491400的评论报告有关简单分配的副作用prototype.
原始答案:
你想从Person的原型对象'继承':
var Person = function(name){
this.name = name;
this.type = 'human';
}
Person.prototype.info = function(){
console.log("Name:", this.name, "Type:", this.type);
}
var Robot = function(name){
Person.apply(this,arguments)
this.name = name;
this.type = 'robot';
}
Robot.prototype = Person.prototype; // Set prototype to Person's
Robot.prototype.constructor = Robot; // Set constructor back to Robot
person = new Person("Bob");
robot = new Robot("Boutros");
person.info();
// Name: Bob Type: human
robot.info();
// Name: Boutros Type: robot
Run Code Online (Sandbox Code Playgroud)
Cal*_*twr 87
我在营地认为Javascript应该尝试没有"新"的生活.它是一种无类语言,它不需要构造函数.您只需创建对象,然后扩展或变形它们.当然,存在陷阱,但这更加强大和简单:
// base `Person` prototype
const Person = {
name : '',
age : 22,
type : 'human',
greet() {
console.log('Hi, my name is ' + this.name + ' and I am a ' + this.type + '.' )
}
}
// create an instance of `Person`:
const skywalker = Object.create(Person)
skywalker.name = 'Anakin Skywalker'
skywalker.greet() // 'Hi, my name is Anakin Skywalker and I am a human.'
Run Code Online (Sandbox Code Playgroud)
// create a `Robot` prototype by extending the `Person` prototype:
const Robot = Object.create(Person)
Robot.type = 'robot'
Robot.variant = '' // add properties for Robot prototype
// Robots speak in binaries, so we need a different greet function:
Robot.greet = function() { //some function to convert strings to binary }
Run Code Online (Sandbox Code Playgroud)
// create a new instance `Robot`
const Astromech = Object.create(Robot)
Astromech.variant = 'astromech'
const r2d2 = Object.create(Astromech)
r2d2.name = 'R2D2'
r2d2.greet() // '0000111010101011100111....'
// morphing the `Robot` object doesn't affect `Person` prototypes
skywalker.greet() // 'Hi, my name is Anakin Skywalker and I am a human.'
Run Code Online (Sandbox Code Playgroud)
**更新3月10日18.采用ES6语法并使用const和let.添加了示例,说明如何使属性不可变.
**更新于1月17日.包括ES6 Object.assign().
如您所见,分配需要多个语句.使用ES6,您可以使用#assign方法缩短分配.(对于在旧版浏览器上使用的polyfill,请参阅ES6上的MDN.)
//instead of this
const Robot = Object.create(Person)
Robot.name = "Robot"
Robot.madeOf = "metal"
Robot.powerConsumption_kW = 5
//you can do this
const Robot = Object.create(Person)
Object.assign(Robot, {
name: "Robot",
madeOf: "metal",
powerConsumption_kWh: 5,
fullCharge_kWh: 10,
currentCharge_kWh: 5
})
//attach some methods unique to Robot prototype.
Robot.charge = function(kWh) {
let self = this
this.currentCharge_kWh = Math.min(self.fullCharge_kWh, self.currentCharge_kWh + kWh)
var percentageCharged = this.currentCharge_kWh / this.fullCharge_kWh * 100
console.log(this.name + (percentageCharged === 100) ? ' is fully charged.' : ' is ' + percentageCharged +'% charged.')
}
Robot.charge(5) // outputs "Robot is fully charged."
Run Code Online (Sandbox Code Playgroud)
你也可以使用Object.create()的第二个参数aka propertiesObject,我发现它有点过于冗长.在#assign上使用它的唯一原因是你需要对值进行更多控制,即可写性/可配置性等等.注意如何Robot严格地用金属制成.
const Robot = Object.create(Person, {
madeOf: {
value: "metal",
writable: false,
configurable: false,
enumerable: true
},
powerConsumption: {
value: "5kWh",
writable: true,
configurable: true,
enumerable: true
}
})
Run Code Online (Sandbox Code Playgroud)
并且所有原型Robot都不能用其他东西制成.
const polymerRobot = Object.create(Robot)
polymerRobot.madeOf = 'polymer'
console.log(polymerRobot.madeOf) // outputs 'metal'
Run Code Online (Sandbox Code Playgroud)
这种模式有些可能导致"经典训练"的程序员绊倒.尽管如此,我发现这种模式更具可读性.
小智 50
如果还没有想出办法,可以使用JavaScript对象的关联属性将扩展函数添加到Object.prototype如下所示.
Object.prototype.extend = function(obj) {
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
this[i] = obj[i];
}
}
};
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用此功能,如下所示.
var o = { member: "some member" };
var x = { extension: "some extension" };
o.extend(x);
Run Code Online (Sandbox Code Playgroud)
Lio*_*rom 29
根据@ osahyoun的回答,我发现以下是从Person的原型对象'继承'的更好和有效的方法:
function Person(name){
this.name = name;
this.type = 'human';
}
Person.prototype.info = function(){
console.log("Name:", this.name, "Type:", this.type);
}
function Robot(name){
Person.call(this, name)
this.type = 'robot';
}
// Set Robot's prototype to Person's prototype by
// creating a new object that inherits from Person.prototype,
// and assigning it to Robot.prototype
Robot.prototype = Object.create(Person.prototype);
// Set constructor back to Robot
Robot.prototype.constructor = Robot;
Run Code Online (Sandbox Code Playgroud)
创建新实例:
var person = new Person("Bob");
var robot = new Robot("Boutros");
person.info(); // Name: Bob Type: human
robot.info(); // Name: Boutros Type: robot
Run Code Online (Sandbox Code Playgroud)
现在,通过使用Object.create:
Person.prototype.constructor !== Robot
Run Code Online (Sandbox Code Playgroud)
另请查看MDN文档.
KrI*_*HnA 23
在ES6中,有Object.assign复制属性值.{}如果您不想修改目标对象(传递的第一个参数),请将其用作第一个参数.
Object.assign
有关详情,请参阅链接,
如果您需要的是Polyfill for ES5,链接也提供它.:)
Har*_*old 18
另一年后,我可以告诉你还有另一个很好的答案.
如果您不喜欢原型设计的工作方式以扩展对象/类,请参考:https://github.com/haroldiedema/joii
可能性的快速示例代码(以及更多):
var Person = Class({
username: 'John',
role: 'Employee',
__construct: function(name, role) {
this.username = name;
this.role = role;
},
getNameAndRole: function() {
return this.username + ' - ' + this.role;
}
});
var Manager = Class({ extends: Person }, {
__construct: function(name)
{
this.super('__construct', name, 'Manager');
}
});
var m = new Manager('John');
console.log(m.getNameAndRole()); // Prints: "John - Manager"
Run Code Online (Sandbox Code Playgroud)
Ali*_*baz 10
那些仍在努力寻求简单和最佳方法的人,可以Spread Syntax用来扩展对象.
var person1 = {
name: "Blank",
age: 22
};
var person2 = {
name: "Robo",
age: 4,
height: '6 feet'
};
// spread syntax
let newObj = { ...person1, ...person2 };
console.log(newObj.height);Run Code Online (Sandbox Code Playgroud)
注意:请记住,最右边的属性将具有优先权.在这个例子中,person2在右侧,因此newObj将在其中包含名称Robo.
Mozilla'宣布'从ECMAScript 6.0扩展的对象:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends
注意:这是一项实验技术,是ECMAScript 6(Harmony)提案的一部分.
class Square extends Polygon {
constructor(length) {
// Here, it calls the parent class' constructor with lengths
// provided for the Polygon's width and height
super(length, length);
// Note: In derived classes, super() must be called before you
// can use 'this'. Leaving this out will cause a reference error.
this.name = 'Square';
}
get area() {
return this.height * this.width;
}
set area(value) {
this.area = value; }
}
Run Code Online (Sandbox Code Playgroud)
这项技术可在Gecko(谷歌浏览器/火狐) - 2015年3月夜间版本中使用.
在大多数项目中都有一些对象扩展的实现:underscore、jquery、lodash: extend。
还有纯 javascript 实现,它是 ECMAscript 6 的一部分:Object.assign: https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
| 归档时间: |
|
| 查看次数: |
254991 次 |
| 最近记录: |