javascript - 在原型(prototype)继承中创建新对象时如何覆盖函数?

标签 javascript inheritance javascript-objects

<分区>

来自 this blog post我们有这个 JavaScript 原型(prototype)继承的例子:

var human = {
    name: '',
    gender: '',
    planetOfBirth: 'Earth',
    sayGender: function () {
        alert(this.name + ' says my gender is ' + this.gender);
    },
    sayPlanet: function () {
        alert(this.name + ' was born on ' + this.planetOfBirth);
    }
};

var male = Object.create(human, {
    gender: {value: 'Male'}
});

var female = Object.create(human, {
    gender: {value: 'Female'}
});

var david = Object.create(male, {
    name: {value: 'David'},
    planetOfBirth: {value: 'Mars'}
});

var jane = Object.create(female, {
    name: {value: 'Jane'}
});

david.sayGender(); // David says my gender is Male
david.sayPlanet(); // David was born on Mars

jane.sayGender(); // Jane says my gender is Female
jane.sayPlanet(); // Jane was born on Earth

现在,我想知道如何正确地“覆盖”,例如 sayPlanet 函数?

我试过这样的:

jane.sayPlanet = function(){
    console.log("something different");
};

这行得通。

不过,我也这样试过:

var jane = Object.create(female, {
    name: {value: 'Jane'},

    sayPlanet: function(){
        console.log("something different");
    }
});

但是我得到一个类型错误。

我的问题是:

  • 如何在 Object.create 中添加 sayPlanet 函数?
  • 这到底是“好方法”还是有更好的(最佳实践)方法?

编辑: 我想出了一种方法可以将 sayPlanet 添加到 Object.create 中:

sayPlanet: {
    value: function(){
        console.log("something different");
    }
}

然而,第二个问题仍然存在。另外,如果有人可以更深入地解释它,如果这是像这样使用它的“好方法”,我将不胜感激。

编辑 #2: 正如 Mahavir 在下面指出的,这是一个糟糕的例子,因为事实证明你不能(如果我错了请纠正我 ) 在 Object.created 之后更改 janename

编辑#3:(伙计,伙计,这会让我进入某个人们穿着白大衣的设施)。正如@WhiteHat 在下面指出的那样,您确实可以将名称属性设置为可更新,如下所示:

var jane = Object.create(female, {
    name: {
        value: 'Jane',
        writable: true
    }
});

然后您可以执行 jane.name="Jane v2.0";

老实说,面对如此多的选择,我不知道该往哪个方向走。就在今天,我读了 Eric Elliot https://medium.com/javascript-scene/the-two-pillars-of-javascript-ee6f3281e7f3现在我不知道该怎么想了,因为他继续争辩说 ES6 的人做得不太对:O。嗯,我想我将不得不再次重温 Crockfords 的书,决定“单向”,看看它能带我走多远。

最佳答案

据我所知,最佳实践是在对象原型(prototype)级别定义写入权限。我从阅读 Addy Osmani 的 JavaScript 设计模式中学到了这项技术,它非常有名并且在线开源:http://addyosmani.com/resources/essentialjsdesignpatterns/book/

请查看下面示例中的 sayPlanet 属性。请记住,您不需要将所有其他属性的“可写”设置为 false,我只是在我的示例代码中这样做来说明这一点。与其他仍然有效的方法相比,这种方法提供了更大的灵 active 和可重用性。在这里,您可能会注意到这是原型(prototype)中的 Object.defineProperties 语法。

var human = {
  name: {
    value: '',
    writable: false //only to illustrate default behavior not needed
  },
  gender: {
    value: '',
    writable: false //only to illustrate default behavior not needed
  },
  planetOfBirth: {
    value: "Earth",
    configurable: false //only to illustrate default behavior not needed
  }

};

//here we define function properties at prototype level

Object.defineProperty(human, 'sayGender', {
  value: function() {
    alert(this.name + ' says my gender is ' + this.gender);
  },
  writable: false
});

Object.defineProperty(human, 'sayPlanet', {
  value: function() {
    alert(this.name + ' was born on ' + this.planetOfBirth);
  },
  writable: true
});

//end definition of function properties

var male = Object.create(human, {
  gender: {
    value: 'Male'
  }
});

var female = Object.create(human, {
  gender: {
    value: 'Female'
  }
});

var david = Object.create(male, {
  name: {
    value: 'David'
  },
  planetOfBirth: {
    value: 'Mars'
  }
});

var jane = Object.create(female, {
  name: {
    value: 'Jane'
  }
});

//define the writable sayPlanet function for Jane
jane.sayPlanet = function() {
  alert("something different");
};

//test cases

//call say gender before attempting to ovverride
david.sayGender(); // David says my gender is Male

//attempt to override the sayGender function for david 
david.sayGender = function() {
  alert("I overrode me!")
};
//I tried and failed to change an unwritable fucntion
david.sayGender(); //David maintains that my gender is Male

david.sayPlanet(); // David was born on Mars

jane.sayGender(); // Jane says my gender is Female
jane.sayPlanet(); // something different

关于javascript - 在原型(prototype)继承中创建新对象时如何覆盖函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32715203/

相关文章:

javascript - 奇怪的useEffect无限循环

java - 捕获返回基类型或派生类型的方法的返回值

c# - 通过继承使用 IDisposable

javascript - 以简洁的方式用模式初始化对象

javascript - 绘制到第二个 Canvas 会取消第一个 Canvas

javascript - 在加载任何其他内容之前重新加载一次页面

javascript - typescript :有没有像联合类型一样工作的东西,除了我们可以访问并非所有联合类型都通用的属性?

java - java中的二维数组列表和类继承

javascript - 如何访问对象集合中实例的 'this'

javascript - 在 javascript 中创建对象并操作属性