两个 JavaScript 对象具有相同的属性实现方式,但原型不同

two javascript objects with same way of implementing properties but different prototype

本文关键字:方式 实现 原型 属性 对象 JavaScript 两个      更新时间:2023-09-26

我正在尝试创建 2 个共享相同实现方式的对象:

function Human(hand,leg,head,body,foot1,foot2){
  this.hand = hand;
  this.leg = leg;
  this.head = head;
  this.body = body;
  this.feet = [foot1,foot2];
}

function Robot(hand,leg,head,body,foot1,foot2){
  this.hand = hand;
  this.leg = leg;
  this.head = head;
  this.body = body;
  this.feet = [foot1,foot2];
}

我希望他们有不同的原型:

Human.prototype.scream = function(){ 
    alert("HUMANNN"); 
    //some other functions 
};
Robot.prototype.scream = function(){ 
     console.log("ROBOOBOT"); 
    //some other functions 
};
var Tom = new Robot(1,2,3,4,5,6);
Tom.scream();
var I = new Human(312314123,2141123,213131412,4121312,132124,12313);
I.scream();

有没有更好的方法来创建函数HumanRobot这样我就不必写两次了?

我试过了

function Robot(hand,leg,head,body,foot1,foot2){
 Human(hand,leg,head,body,foot1,foot2);
}
var Micky = new Robot(1,2,3,4,5,6);
Micky.scream();

但它没有用。

我试过了

function Robot(hand,leg,head,body,foot1,foot2){
    Human(hand,leg,head,body,foot1,foot2);
}

这确实将Human作为函数调用,而不是作为构造函数 - 不是在实例上,而是将全局对象作为this值。您需要使用.call

function Robot(hand,leg,head,body,foot1,foot2) {
    Human.call(this, hand,leg,head,body,foot1,foot2);
}

或者,如果您不想将它们写出来,可以使用 arguments 对象并apply

function Robot() {
    Human.apply(this, arguments);
}
但是,与其从一个构造函数调用

另一个构造函数,我建议将公共代码放入泛型构造函数中,并从HumanRobot调用它,以便您也可以将特定的实例初始化代码放在它们的构造函数中:

function Humanoid (hand, leg, head, body, foot1, foot2) {
    this.hand = hand;
    this.leg = leg;
    this.head = head;
    this.body = body;
    this.feet = [foot1, foot2]
}
function Human() {
    Humanoid.apply(this, arguments);
    …
}
// if you want Humans to inherit Humanoid prototype properties:
// Human.prototype = Object.create(Humanoid.prototype);
Human.prototype.… = …;
function Robot() {
    Humanoid.apply(this, arguments);
    …
}
// if you want Robots to inherit Humanoid prototype properties:
// Robot.prototype = Object.create(Humanoid.prototype);
Robot.prototype.… = …;

一种创建人类和机器人函数的方法,这样我就不必写两次了?

如果您确定构造函数代码始终完全相同,则还可以使用闭包:

function getConstructor() {
    return function Human(hand,leg,head,body,foot1,foot2) {
        this.hand = hand;
        this.leg = leg;
        this.head = head;
        this.body = body;
        this.feet = [foot1,foot2];
    }
}
var Human = getConstructor();
Human.prototype.… = …;
var Robot = getConstructor();
Robot.prototype.… = …;

您可以创建一个 mixin 函数,该函数将属性添加到构造函数并使用适当的上下文调用它。你也可以使用一个对象来代替这么多参数:

function mixin(props) {
  for (var prop in props) {
    this[prop] = props[prop];
  }
}
function Human(props) {
  mixin.call(this, props);
}
function Robot(props) {
  mixin.call(this, props);
}
Human.prototype.scream = function() {
  console.log('Human has '+ this.legs.length +' legs'); 
};
Robot.prototype.scream = function() { 
  console.log('Robot has '+ this.legs.length +' legs'); 
};
var human = new Human({
  head: 1,
  body: 1,
  hand: 1,
  legs: [1,2],
  feet: [1,2]
});
var robot = new Robot({
  head: 1,
  body: 1,
  hand: 1,
  legs: [1,2,3],
  feet: [1,2,3]
});

你需要的是申请或调用

// with call
function Robot(hand,leg,head,body,foot1,foot2){
  Human.call(this, hand, leg, head, body, foot1, foot2);
}
var you = new Robot(1,2,3,4,5,6);
you.scream();
// with apply
function Robot(hand,leg,head,body,foot1,foot2){
  Human.apply(this, arguments);
}
var you = new Robot(1,2,3,4,5,6);
you.scream();

使用 apply,您基本上按照从原始函数获得的相同顺序传递所有参数。

更好的OOP方法

// From "Pro Javascript Design Patterns" by Ross Harmes and Dustin Diaz
function extend(subClass,superClass) {
    var F = function() {};
    F.prototype = superClass.prototype;
    subClass.prototype = new F();
    subClass.prototype.constructor = subClass;
    subClass.superClass = superClass.prototype;
    if(superClass.prototype.constructor == Object.prototype.constructor) {
        superClass.prototype.constructor = superClass;
    }
}
function Humanoid(hand,leg,head,body,foot1,foot2){
    this.hand = hand;
    this.leg = leg;
    this.head = head;
    this.body = body;
    this.feet = [foot1,foot2];
}
function Robot() {
    Robot.superClass.constructor.apply(this,arguments);
}
extend(Robot,Humanoid);
function Human() {
    Human.superClass.constructor.apply(this,arguments);
}
extend(Human,Humanoid);
var John = new Human(2,2,1,1,1,1);
console.log(John);

为什么不为人类和机器人创建一个通用原型,而只覆盖尖叫功能:

function HumanRobotProt(hand,leg,head,body,foot1,foot2){
  this.hand = hand;
  this.leg = leg;
  this.head = head;
  this.body = body;
  this.feet = [foot1,foot2];
}
Human.prtotype = new HumanRobotProt;
Robot.prototype = new HumanRobotProt;
function Human(hand,leg,head,body,foot1,foot2){
    Human.call(this, hand,leg,head,body,foot1,foot2);
    this.scream = function(){ 
    alert("HUMANNN"); 
}
function Robot(hand,leg,head,body,foot1,foot2){
    Robot.call(this, hand,leg,head,body,foot1,foot2);
    this.scream = function(){ 
    alert("ROBOOOT"); 
}