在Javascript中扩展对象
我目前正在从Java转换到Javascript,对于如何按照我希望的方式来扩展对象,我有点困难。
我看到互联网上有几个人使用了一种叫做“在对象上扩展”的方法。 代码将如下所示:
var Person = { name : 'Blank', age : 22 } var Robot = Person.extend({ name : 'Robo', age : 4 )} var robot = new Robot(); alert(robot.name); //Should return 'Robo'
有谁知道如何使这项工作? 我听说你需要写
Object.prototype.extend = function(...);
但我不知道如何使这个系统工作。 如果这是不可能的,请给我看另一个扩展对象的select。
编辑 :
在使用代码之前,请检查user2491400中有关简单分配给prototype
副作用的评论。
原始答案:
你想从Person的原型对象“inheritance”:
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
没有“新”关键字的世界。
用Object.create()更简单的语法。
我在信奉Javascript的阵营中应该尝试没有“新”的生活。 这是一种无阶级的语言,它不需要构造函数。 您只需创build对象,然后对其进行扩展或变形即可。 当然,这是有缺陷的,但是这是非常强大和简单的:
// base `Person` prototype var Person = { name : '', age : 22, type : 'human', greet: function() { console.log('Hi, my name is ' + this.name + ' and I am a ' + this.type + '.' ); } }; // create an instance of `Person`: var skywalker = Object.create(Person); skywalker.name = 'Anakin Skywalker'; skywalker.greet(); // 'Hi, my name is Anakin Skywalker and I am a human.'
扩展基础原型
// create a `Robot` prototype by extending the `Person` prototype: var 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 }
再深一层
// create a new instance `Robot` var Astromech = Object.create(Robot); Astromech.variant = 'astromech'; var 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.'
进一步阅读
**更新1月22日17.包括ES6 Object.assign()。
正如你所看到的,任务需要多个语句。 使用ES6,您可以使用#assign方法来缩短分配。 (要在较旧的浏览器上使用polyfill ,请参阅ES6上的MDN 。)
//instead of this var Robot = Object.create(Person); Robot.name = "Robot"; Robot.madeOf = "metal"; Robot.powerConsumption_kW = 5; //you can do this var 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) { var 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." //you can also use Object.create()'s second argument aka propertiesObject, //which I find to be a little too lengthy. The only reason to use it over #assign is if you need more control over the values ie writability/configurability etc... var Robot = Object.create(Person, { madeOf: { value: "metal", writable: true, configurable: true, enumerable: true }, powerConsumption: { value: "5kWh", writable: true, configurable: true, enumerable: true } });
这种模式有一些陷阱,可能会出现“古典训练”的程序员。 尽pipe如此,我发现这种模式更具可读性。
如果您还没有find一种方法,请使用JavaScript对象的关联属性将扩展函数添加到Object.prototype
,如下所示。
Object.prototype.extend = function(obj) { for (var i in obj) { if (obj.hasOwnProperty(i)) { this[i] = obj[i]; } } };
然后你可以使用这个function,如下所示。
var o = { member: "some member" }; var x = { extension: "some extension" }; o.extend(x);
不同的方法: Object.create
根据@osahyoun的回答,我发现以下是从Person的原型对象'inheritance'的更好和有效的方法:
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 Robot.prototype = Object.create(Person.prototype); // Set constructor back to Robot Robot.prototype.constructor = Robot; person = new Person("Bob"); robot = new Robot("Boutros"); person.info(); // Name: Bob Type: human robot.info(); // Name: Boutros Type: robot
现在,通过使用Object.create , Person.prototype.constructor !== Robot
检查MDN文档。
再过一年,我可以告诉你还有一个很好的答案。
如果你不喜欢原型的工作方式来扩展对象/类,请点击这里: 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"
在ES6中 ,有用于复制属性值的Object.assign
。 使用{}
作为第一个参数,如果你不想修改目标对象(第一个parameter passing)。
var resultObj = Object.assign({},Obj1,Obj2);
有关更多详情,请参阅链接
MDN – Object.assign()
如果你需要的是一个用于ES5的Polyfill ,链接也提供它。 🙂
您可能需要考虑使用像underscore.js这样的助手库,它有自己的extend()
。
通过查看源代码,这也是学习的好方法。 注释的源代码页是非常有用的。
Mozilla'宣布'从ECMAScript 6.0扩展的对象:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends
注意:这是一个实验技术,是ECMAScript 6(和谐)提案的一部分。
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; } }
Gecko(谷歌浏览器/火狐浏览器) – 2015年3月每晚构build这项技术。
在大多数项目中都有一些对象扩展的实现:下划线,jQuery,lodash: extend 。
还有纯粹的JavaScript实现,这是ECMAscript 6的一部分: Object.assign : https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Function.prototype.extends=function(ParentClass) { this.prototype = new ParentClass(); this.prototype.constructor = this; }
然后:
function Person() { this.name = "anonym" this.skills = ["abc"]; } Person.prototype.profile = function() { return this.skills.length // 1 }; function Student() {} //well extends fom Person Class Student.extends(Person) var s1 = new Student(); s1.skills.push("") s1.profile() // 2
更新01/2017:
请忽略我2015年的答案,因为Javascript现在支持extends
关键字自ES6(Ecmasctipt6)
– ES6:
class Person { constructor() { this.name = "anonym" this.skills = ["abc"]; } profile() { return this.skills.length // 1 } } Person.MAX_SKILLS = 10; class Student extends Person { } //well extends from Person Class //----------------- var s1 = new Student(); s1.skills.push("") s1.profile() // 2
– ES7:
class Person { static MAX_SKILLS = 10; name = "anonym" skills = ["abc"]; profile() { return this.skills.length // 1 } } class Student extends Person { } //well extends from Person Class //----------------- var s1 = new Student(); s1.skills.push("") s1.profile() // 2
你可以简单地通过使用:
Object.prototype.extend = function(object) { // loop through object for (var i in object) { // check if the extended object has that property if (object.hasOwnProperty(i)) { // mow check if the child is also and object so we go through it recursively if (typeof this[i] == "object" && this.hasOwnProperty(i) && this[i] != null) { this[i].extend(object[i]); } else { this[i] = object[i]; } } } return this; };
更新:我检查了
this[i] != null
因为null
是一个对象
然后像这样使用它:
var options = { foo: 'bar', baz: 'dar' } var defaults = { foo: false, baz: 'car', nat: 0 } defaults.extend(options);
这导致:
// defaults will now be { foo: 'bar', baz: 'dar', nat: 0 }
-
不需要使用任何外部库来扩展
-
在JavaScript中,一切都是一个对象(三种基本数据types除外,即使它们在需要时也会自动包装在对象中)。 而且,所有对象都是可变的。
JavaScript中的类人员
function Person(name, age) { this.name = name; this.age = age; } Person.prototype = { getName: function() { return this.name; }, getAge: function() { return this.age; } } /* Instantiate the class. */ var alice = new Person('Alice', 93); var bill = new Person('Bill', 30);
修改特定的实例/对象 。
alice.displayGreeting = function() { alert(this.getGreeting()); }
修改类
Person.prototype.getGreeting = function() { return 'Hi ' + this.getName() + '!'; };
或者简单地说:扩展JSON和OBJECT都是一样的
var k = { name : 'jack', age : 30 } k.gender = 'male'; /*object or json k got extended with new property gender*/
感谢ross harmes,dustin diaz
原型是一个不错的方法,但原型有时是相当危险的,可能会导致错误。 我更喜欢把它封装到一个基础对象中,就像Ember.js对Ember.Object.extend和Ember.Object.reopen所做的那样。 这是更安全的使用。
我创build了一个如何设置类似于 Ember.Object使用的东西的要点。
这里的链接: https : //gist.github.com/WebCloud/cbfe2d848c80d4b9e9bd