在 Javascript 中扩展对象

Posted

技术标签:

【中文标题】在 Javascript 中扩展对象【英文标题】:Extending an Object in Javascript 【发布时间】:2012-05-12 21:40:31 【问题描述】:

我目前正在从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'

有谁知道如何进行这项工作? 我听说你需要写

Object.prototype.extend = function(...);

但我不知道如何使这个系统工作。如果不可能,请告诉我另一个扩展对象的替代方法。

【问题讨论】:

返回真;但这就是我问的原因:) 我建议在 MDN 上阅读这个漂亮的教程:- developer.mozilla.org/en/… 如果您在阅读了那些不错的文档后仍然对 extend 函数感到好奇,我在这里设置了一个示例:jsfiddle.net/k9LRd 我还建议不要将其严格地视为“从 Java 转换为 JavaScript”,而应将其视为“学习一种与 Java 具有相似语法的新语言 Javascript” 【参考方案1】:

您想从 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.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

【讨论】:

我有一个问题:当您执行new Robot() 时,如何调用Person() 构造函数?在我看来,您应该调用该基类构造函数,而不是在 Robot() 构造函数中执行 this.name = name;... @AlexisWilke:是的,你应该打电话给Person.apply(this, arguments);。最好使用Robot.prototype = Object.create(Person.prototype); 而不是new Person(); 正如菲利克斯所说,'Robot.prototype = Person.prototype;'如果有人希望“机器人”类型拥有自己的原型实例,那么这是一个坏主意。添加新的机器人特定功能也会将其添加到人员。 这个例子是完全错误的。通过这样做,您可以更改 Person 的原型。这不是继承,您可能会在 Person 类中造成巨大的混乱。请参阅建议使用 Object.create() 的答案。这才是做事的正确方式。 @osahyoun 这个答案在谷歌搜索中排名很高。我真的建议您按照此处其他 cmets 的建议修复代码并更正原型链。【参考方案2】:

没有“new”关键字的世界。

使用 Object.create() 并使用更简单的“散文式”语法。

*此示例针对 ES6 类和 TypeScript 进行了更新。

首先,Javascript 是 prototypal language,不是基于类的。它的真实性质以下面的原型形式表达,您可能会发现它非常简单,像散文,但功能强大。

TLDR;

Javascript

const Person =  
    name: 'Anonymous', // person has a name
    greet: function()  console.log(`Hi, I am $this.name.`)  
 
    
const jack = Object.create(Person)   // jack is a person
jack.name = 'Jack'                   // and has a name 'Jack'
jack.greet()                         // outputs "Hi, I am Jack."

打字稿

在 TypeScript 中,您需要设置接口,这些接口将在您创建 Person 原型的后代时进行扩展。突变politeGreet 显示了在后代jack 上附加新方法的示例。

interface Person 
    name: string
    greet(): void


const Person =  
    name:  'Anonymous',  
    greet() 
        console.log(`Hi, I am $this.name.`)
    


interface jack extends Person 
    politeGreet: (title: 'Sir' | 'Mdm') => void


const jack: jack = Object.create(Person)
jack.name = 'Jack'
jack.politeGreet = function(title) 
    console.log(`Dear $title! I am $this.name.`)

jack.greet()  // "Hi, I am Jack."
jack.politeGreet('Sir') // "Dear Sir, I am Jack."

这消除了有时令人费解的构造函数模式。 新对象继承自旧对象,但能够拥有自己的属性。如果我们尝试从新对象 (#greet()) 中获取新对象 jack 缺少的成员,则旧对象 Person 将提供该成员。

在Douglas Crockford's words: "Objects inherit from objects. What could be more object-oriented than that?"

您不需要构造函数,也不需要 new 实例化。您只需创建对象,然后扩展或变形它们。

此模式还提供immutability (partial or full) 和getters/setters。

干净整洁。它的简单性不会影响功能。继续阅读。

创建 Person prototype 的后代/副本(技术上比 class 更正确)。

*注意:以下示例是在 JS 中。要使用 Typescript 编写,只需按照上面的示例设置输入接口即可。

const Skywalker = Object.create(Person)
Skywalker.lastName = 'Skywalker'
Skywalker.firstName = ''
Skywalker.type = 'human'
Skywalker.greet = function()  console.log(`Hi, my name is $this.firstName $this.lastName and I am a $this.type.`

const anakin = Object.create(Skywalker)
anakin.firstName = 'Anakin'
anakin.birthYear = '442 BBY'
anakin.gender = 'male' // you can attach new properties.
anakin.greet() // 'Hi, my name is Anakin Skywalker and I am a human.'

Person.isPrototypeOf(Skywalker) // outputs true
Person.isPrototypeOf(anakin) // outputs true
Skywalker.isPrototypeOf(anakin) // outputs true

如果您觉得丢弃构造函数而不是直接赋值不太安全,一种常见的方法是附加 #create 方法:

Skywalker.create = function(firstName, gender, birthYear) 

    let skywalker = Object.create(Skywalker)

    Object.assign(skywalker, 
        firstName,
        birthYear,
        gender,
        lastName: 'Skywalker',
        type: 'human'
    )

    return skywalker


const anakin = Skywalker.create('Anakin', 'male', '442 BBY')

Person 原型分支到Robot

当你从Person原型分支Robot后代时,你不会影响Skywalkeranakin

// create a `Robot` prototype by extending the `Person` prototype:
const Robot = Object.create(Person)
Robot.type = 'robot'

附加Robot独有的方法

Robot.machineGreet = function()  
    /*some function to convert strings to binary */ 


// Mutating the `Robot` object doesn't affect `Person` prototype and its descendants
anakin.machineGreet() // error

Person.isPrototypeOf(Robot) // outputs true
Robot.isPrototypeOf(Skywalker) // outputs false

在 TypeScript 中,您还需要扩展 Person 接口:

interface Robot extends Person 
    machineGreet(): void

const Robot: Robot = Object.create(Person)
Robot.machineGreet = function()  console.log(101010) 

而且你可以拥有 Mixins——因为……Darth Vader 是人类还是机器人?

const darthVader = Object.create(anakin)
// for brevity, property assignments are skipped because you get the point by now.
Object.assign(darthVader, Robot)

Darth Vader 获取Robot 的方法:

darthVader.greet() // inherited from `Person`, outputs "Hi, my name is Darth Vader..."
darthVader.machineGreet() // inherited from `Robot`, outputs 001010011010...

还有其他奇怪的事情:

console.log(darthVader.type) // outputs robot.
Robot.isPrototypeOf(darthVader) // returns false.
Person.isPrototypeOf(darthVader) // returns true.

优雅地反映了“现实生活”的主观性:

“他现在比人更像机器,扭曲而邪恶。” - 欧比旺克诺比

“我知道你很优秀。” - 卢克天行者

与 ES6 之前的“经典”等效项进行比较:

function Person (firstName, lastName, birthYear, type) 
    this.firstName = firstName 
    this.lastName = lastName
    this.birthYear = birthYear
    this.type = type


// attaching methods
Person.prototype.name = function()  return firstName + ' ' + lastName 
Person.prototype.greet = function()  ... 
Person.prototype.age = function()  ... 

function Skywalker(firstName, birthYear) 
    Person.apply(this, [firstName, 'Skywalker', birthYear, 'human'])


// confusing re-pointing...
Skywalker.prototype = Person.prototype
Skywalker.prototype.constructor = Skywalker

const anakin = new Skywalker('Anakin', '442 BBY')

// #isPrototypeOf won't work
Person.isPrototypeOf(anakin) // returns false
Skywalker.isPrototypeOf(anakin) // returns false

ES6 类

与使用对象相比更笨拙,但代码可读性还可以:

class Person 
    constructor(firstName, lastName, birthYear, type) 
        this.firstName = firstName 
        this.lastName = lastName
        this.birthYear = birthYear
        this.type = type
    
    name()  return this.firstName + ' ' + this.lastName 
    greet()  console.log('Hi, my name is ' + this.name() + ' and I am a ' + this.type + '.' ) 


class Skywalker extends Person 
    constructor(firstName, birthYear) 
        super(firstName, 'Skywalker', birthYear, 'human')
    


const anakin = new Skywalker('Anakin', '442 BBY')

// prototype chain inheritance checking is partially fixed.
Person.isPrototypeOf(anakin) // returns false!
Skywalker.isPrototypeOf(anakin) // returns true

进一步阅读

可写性、可配置性和免费的 Getter 和 Setter!

对于免费的 getter 和 setter,或额外的配置,您可以使用 Object.create() 的第二个参数,也就是 propertiesObject。它也可以在#Object.defineProperty 和#Object.defineProperties 中使用。

为了说明其用途,假设我们希望所有Robot 都严格由金属制成(通过writable: false),并标准化powerConsumption 值(通过getter 和setter)。


// Add interface for Typescript, omit for Javascript
interface Robot extends Person 
    madeOf: 'metal'
    powerConsumption: string


// add `: Robot` for TypeScript, omit for Javascript.
const Robot: Robot = Object.create(Person, 
    // define your property attributes
    madeOf:  
        value: "metal",
        writable: false,  // defaults to false. this assignment is redundant, and for verbosity only.
        configurable: false, // defaults to false. this assignment is redundant, and for verbosity only.
        enumerable: true  // defaults to false
    ,
    // getters and setters
    powerConsumption: 
        get()  return this._powerConsumption ,
        set(value)  
            if (value.indexOf('MWh')) return this._powerConsumption = value.replace('M', ',000k') 
            this._powerConsumption = value
            throw new Error('Power consumption format not recognised.')
          
    
)

// add `: Robot` for TypeScript, omit for Javascript.
const newRobot: Robot = Object.create(Robot)
newRobot.powerConsumption = '5MWh'
console.log(newRobot.powerConsumption) // outputs 5,000kWh

并且Robot 的所有原型都不能是madeOf 别的东西:

const polymerRobot = Object.create(Robot)
polymerRobot.madeOf = 'polymer'
console.log(polymerRobot.madeOf) // outputs 'metal'

【讨论】:

- Object.create 在许多(旧)浏览器中不存在,尤其是 Internet Explorer 8 及更低版本。 - Object.create() 仍然调用你通过它的函数的构造函数。 - 对于每个属性声明,您必须一遍又一遍地配置相同的设置(如示例代码中所示)。使用 Object.create 代替 new 关键字并没有真正的好处。 “受过经典训练的”程序员,你这是什么意思? 我来自经典的 OOP 思维方式,这个答案对我帮助很大。关于代码的两个问题:1)今天的 ES2015 Object.assign(Robot, a:1 是您的 extend() 方法的好替代品吗? 2) 如何覆盖greet() 方法,使其返回相同的文本,但附加“a greet override”? 1) #Object.assign 看起来确实是个不错的选择。但浏览器支持较低的atm。 2) 您将使用对象的__proto__ 属性来访问其原型的问候功能。然后你调用原型 greet 函数并传入被调用者的范围。在这种情况下,该函数是一个控制台日志,因此不可能“附加”。但是通过这个例子,我认为你明白了。 skywalker.greet = function() this.__proto__.greet.call(this); console.log('a greet override'); 嗯,这是应该与 ECMAScript 语言规范维护者进行的讨论。我大体上同意,但我必须使用我所拥有的。【参考方案3】:

如果您还没有想出办法,请使用 JavaScript 对象的关联属性将扩展函数添加到 Object.prototype,如下所示。

Object.prototype.extend = function(obj) 
   for (var i in obj) 
      if (obj.hasOwnProperty(i)) 
         this[i] = obj[i];
      
   
;

然后您就可以使用该功能,如下所示。

var o =  member: "some member" ;
var x =  extension: "some extension" ;

o.extend(x);

【讨论】:

请注意,在“父”类中使用对象/数组时,这将创建指向“子”类中原始对象的指针。详细说明:如果您的父类中有一个对象或数组,则在扩展该基类的子类中对其进行修改,实际上将针对在同一基类上扩展的所有子类进行修改。 Harold,感谢您强调这一事实。对于使用该函数的人来说,加入一个检查对象/数组并复制它们的条件是很重要的。【参考方案4】:

在 ES6 中,你可以使用扩展操作符

var mergedObj =  ...Obj1, ...Obj2 ;

请注意,Object.assign() 会触发 setter,而传播语法则不会。

更多信息见链接,MDN -Spread Syntax


旧答案:

在 ES6 中,Object.assign 用于复制属性值。如果您不想修改目标对象(传递的第一个参数),请使用 作为第一个参数。

var mergedObj = Object.assign(, Obj1, Obj2);

更多详情见链接,MDN - Object.assign()

如果您需要 用于 ES5 的 Polyfill,该链接也提供了它。 :)

【讨论】:

【参考方案5】:

不同的方法:Object.create

根据@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;

创建新实例:

var person = new Person("Bob");
var robot = new Robot("Boutros");

person.info(); // Name: Bob Type: human
robot.info();  // Name: Boutros Type: robot

现在,使用Object.create:

Person.prototype.constructor !== Robot

还要查看MDN 文档。

【讨论】:

只想说@GaretClaborn它工作正常,但你没有将name参数传递给父构造函数,像这样:jsfiddle.net/3brm0a7a/3(区别在第8行)跨度> @xPheRe 啊,我明白了,谢谢。我编辑了答案以反映这种变化 @xPheRe,我想当我添加这个解决方案时,我更专注于证明一个观点。谢谢。 不错的答案 +1,您可以查看 ECMAScript 6。关键字类和扩展可用:developer.mozilla.org/en-US/docs/Web/JavaScript/…【参考方案6】:

又过了一年,我可以告诉你还有另一个不错的答案。

如果您不喜欢原型设计以扩展对象/类的方式,请查看: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"

【讨论】:

好吧,我还有 2 个月的时间,直到 2 年结束 :P 不管怎样,JOII 3.0 即将发布 :) 3 年后制作。 有趣的概念,但语法看起来真的很难看。你最好等待 ES6 类变得稳定 我完全同意@sleepycal。但不幸的是,在所有主要/常见浏览器都实现这一点之前,至少还需要 5 年时间。所以在那之前,这将不得不做......【参考方案7】:

还在为最简单最好的方法而苦苦挣扎的人,可以使用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);

注意:请记住,最右边的属性将具有优先权。在本例中,person2 位于右侧,因此 newObj 将在其中包含名称 Robo

【讨论】:

【参考方案8】:

您可能需要考虑使用像 underscore.js 这样的辅助库,它有 it's own implementation of extend()

通过查看它的源代码,这也是一种学习的好方法。 annotated source code page 非常有用。

【讨论】:

一个 underscore.js 的 _.extend() 工作原理的示例使其功能非常清晰:lostechies.com/chrismissal/2012/10/05/…【参考方案9】:

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;      

Gecko (Google Chrome / Firefox) - 03/2015 nightly builds 中提供了这项技术。

【讨论】:

【参考方案10】:

在大多数项目中都有一些对象扩展的实现:下划线、jquery、lodash:extend

还有纯 javascript 实现,它是 ECMAscript 6 的一部分:Object.assign: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

【讨论】:

“纯 javascript 实现”不是指仅用 JavaScript 实现的东西,而不是环境提供的可以本地实现的功能吗? @binki,我的意思是原生 javascript 实现 - ECMAScript 2015 (ES6) 标准的一部分【参考方案11】:
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

2017 年 1 月更新:

请忽略我对 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

【讨论】:

通过在覆盖构造函数之前调用new ParentClass(),您已经执行了父构造函数。如果你问我,我认为那不是正确的行为......【参考方案12】:

总结:

Javascript 使用一种称为原型继承 的机制。在查找对象的属性时使用原型继承。当我们在 javascript 中扩展属性时,我们是从实际对象继承这些属性。它的工作方式如下:

    当请求对象属性时(例如myObj.foomyObj['foo']),JS 引擎将首先在对象本身上查找该属性 当在对象本身上找不到此属性时,它会爬上原型链查看原型对象。如果这里也没有找到这个属性,它将继续爬上原型链,直到找到该属性。如果未找到该属性,则会引发引用错误。

当我们想在 javascript 中扩展一个对象时,我们可以简单地在原型链中链接这个对象。有很多方法可以实现,我将介绍两种常用的方法。

示例:

1. Object.create()

Object.create() 是一个将对象作为参数并创建新对象的函数。作为参数传递的对象将是新创建对象的原型。例如:

// prototype of the dog
const dogPrototype = 
  woof: function ()  console.log('woof'); 


// create 2 dog objects, pass prototype as an argument
const fluffy = Object.create(dogPrototype);
const notFluffy = Object.create(dogPrototype);

// both newly created object inherit the woof 
// function from the dogPrototype
fluffy.woof();
notFluffy.woof();

2。显式设置原型属性

在使用构造函数创建对象时,我们可以为其原型对象属性设置添加属性。使用new 关键字创建的对象形成构造函数,其原型设置为构造函数的原型。例如:

// Constructor function object
function Dog (name) 
   name = this.name;


// Functions are just objects
// All functions have a prototype property
// When a function is used as a constructor (with the new keyword)
// The newly created object will have the consturctor function's
// prototype as its prototype property
Dog.prototype.woof = function () 
  console.log('woof');


// create a new dog instance
const fluffy = new Dog('fluffyGoodBoyyyyy');
// fluffy inherits the woof method
fluffy.woof();

// can check the prototype in the following manner
console.log(Object.getPrototypeOf(fluffy));

【讨论】:

【参考方案13】:

简单易读的解决方案是使用扩展运算符

...

例如:

const obj1 = a: "a" const obj2 = b: "b" const result = ...obj1, ..obj2, console.log("result", result) // must be a: "a", b: "b"

【讨论】:

【参考方案14】:

您可以简单地使用:

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

【讨论】:

【参考方案15】:

请添加拒绝投票的原因

无需使用任何外部库进行扩展

在 JavaScript 中,一切都是对象(除了这三个 原始数据类型,甚至它们都自动包装 需要时提供对象)。此外,所有对象都是可变的。

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() + '!';
;

或者简单地说:extend JSON 和 OBJECT 都是一样的

var k = 
    name : 'jack',
    age : 30


k.gender = 'male'; /*object or json k got extended with new property gender*/

感谢罗斯·哈姆斯,达斯汀·迪亚兹

【讨论】:

【参考方案16】:

虽然这项工作并非 100% 正确

// Parent
var Parent = function (name) 
  this.name = name;
  this.test = function () 
    console.log("parent test");
  
  this.testOverride = function () 
    console.log("parent testOverride");
  

// define a function extend
Parent.prototype.extend = function () 
  // parent properties to override or add
  var override = arguments[0];
  return function () 
    Parent.apply(this, arguments);
    // add and override properties
    Object.keys(override).forEach(el =>
      this[el] = override[el];
    )
   

// create a Child from the Parent and override
// the function "testOverride" and keep "test" unchanged
var Child = Parent.prototype.extend(
  y: 10,
  testOverride: function ()  
    console.log("child testOverride"); 
  
);
// Create an object of type Parent
var p = new Parent("Parent");
// Create an object of type Child
var c = new Child("Child");
console.log(p.name);
// Parent
console.log(c.name);
// Child
p.test();
//parent test
p.testOverride();
//parent testOverride
c.test();
//parent test
c.testOverride();
//child testOverride

【讨论】:

【参考方案17】:

这将使您的属性扩展创建一个新的对象,其中包含对象参数原型,而不会更改传递的对象。

function extend(object) 
    if (object === null)
        throw TypeError;
    if (typeof object !== "object" && typeof object !== "function")
        throw TypeError;
    if (Object.create)
        return Object.create(object);
    function f() 
    ;
    f.prototype = p;
    return new f();

但是如果你想扩展你的对象而不修改它的参数,你可以将 extendProperty 添加到你的对象中。

var Person
//some code
extend: extendProperty


//Enforce type checking an Error report as you wish
    function extendProperty(object) 
        if ((object !== null && (typeof object === "object" || typeof object === "function")))
            for (var prop in object) 
                if (object.hasOwnProperty(prop))
                    this[prop] = object[prop];
            
        else
            throw TypeError; //Not an object
        
    

【讨论】:

以上是关于在 Javascript 中扩展对象的主要内容,如果未能解决你的问题,请参考以下文章

面向对象的JavaScript --- 封装

JQuery

web-12. JavaScript概述

JS_3浏览器对象

如何在Javascript中从数组中提取值

javascript高级教程JavaScript Number 对象