Javascript-在构造函数中使用左手赋值更改对象

Javascript-在构造函数中使用左手赋值更改对象,javascript,inheritance,extends,Javascript,Inheritance,Extends,我一直在尝试各种方法来模拟Javascript中的经典继承,并且找到了一些方法。然而,我很好奇为什么我不能用一种特殊的方式来做,以及我如何才能尝试解决这个问题 我试过这个: var squeaker = new squeek(); function monsterMaker(newMonster) { newMonster.type = "monster"; newMonster.health = 10; return newMonster; } function s

我一直在尝试各种方法来模拟Javascript中的经典继承,并且找到了一些方法。然而,我很好奇为什么我不能用一种特殊的方式来做,以及我如何才能尝试解决这个问题

我试过这个:

var squeaker = new squeek();

function monsterMaker(newMonster) {
    newMonster.type = "monster";
    newMonster.health = 10;
    return newMonster;
}

function squeek() {
    this.name = "squeek";
    this = monsterMaker(this);
}
我想我理解为什么会发生这种情况,并且我已经找到了解决方法,即jQuery的$.extend,但是有没有一种方法可以通过使用左手赋值或变通方法来改变新创建的对象,而不使用额外的库呢?

您不能分配给它,但您不需要:您的代码,如果它有效,将等同于此代码,它确实起作用:

var squeaker = new squeek();

function monsterMaker(newMonster) {
    newMonster.type = "monster";
    newMonster.health = 10;
    return newMonster;
}

function squeek() {
    this.name = "squeek";
    monsterMaker(this); // sets properties on this
}
虽然JavaScript是按值传递的,但本例中的值是整个this对象的值,因此在某些方面类似于按引用传递。

您不能分配给它,但您不需要:您的代码如果有效,将等效于此代码,它确实有效:

var squeaker = new squeek();

function monsterMaker(newMonster) {
    newMonster.type = "monster";
    newMonster.health = 10;
    return newMonster;
}

function squeek() {
    this.name = "squeek";
    monsterMaker(this); // sets properties on this
}
虽然JavaScript是按值传递的,但本例中的值是该对象的整个值,因此在某些方面类似于按引用传递。

不,您不能将其分配给。然而,你不需要!只需将该实例传递给monsterMaker,该函数就会为其添加一些属性——这正是您所需要的。您不需要返回该对象,也不需要使用返回的对象-仍然是这样

不,您不能分配给。然而,你不需要!只需将该实例传递给monsterMaker,该函数就会为其添加一些属性——这正是您所需要的。您不需要返回该对象,也不需要使用返回的对象-仍然是这样

你应该试试:

var squeaker = new squeek();

function monsterMaker(newMonster) {
    this.type = "monster";
    this.health = 10;
}

function squeek() {
    this.name = "squeek";
    monsterMaker.call(this);
}
通过这种方式,您可以使用monsterMaker函数的属性装饰您想要的任何对象

但是,进一步考虑,我认为您已经到了需要原型继承的地步…

您应该尝试:

var squeaker = new squeek();

function monsterMaker(newMonster) {
    this.type = "monster";
    this.health = 10;
}

function squeek() {
    this.name = "squeek";
    monsterMaker.call(this);
}
通过这种方式,您可以使用monsterMaker函数的属性装饰您想要的任何对象


但是,进一步思考,我认为您已经到了需要原型继承的地步…

这是一种使用原型继承的方法。要查看控制台输出,请在Chrome中按F12或在FireFox中打开FireBug。Chrome将为您提供一个可深入查看的交互式对象

function monsterMaker() {
    this.type = "monster";
    this.health = 10;
}

function squeek() {
    this.name = "squeek";
    //monsterMaker.call(this); // sets properties on this
}
squeek.prototype = new monsterMaker();
squeek.prototype.constructor = monsterMaker;

var squeaker = new squeek();

console.log(squeaker);
console.log(squeaker.name);
console.log(squeaker.type);
console.log(squeaker.health);
请在此处查看它的工作情况:

以下是一些链接:

从上面的第二个MDN链接中,您可以通过新的JavaScript方式来实现ECMAScript 5,从而包括用于扩展的库和示例代码-使用控制台查看示例输出:

// Original Author:  FireFly - Jonas Höglund - ##javascript channel
// on irc.freenode.net - see THANKS File

///////////////
// Library code
///////////////

var ExtendBase = {};

Object.defineProperty(ExtendBase, 'extend', {
    enumerable: false
    , value: function(obj) {
        'use strict';

        var descs = {}
        , objectInheritCounter = 0;

        objectInheritCounter += 1;

        Object.getOwnPropertyNames(obj).forEach(function(key) {
        descs[key] = Object.getOwnPropertyDescriptor(obj, key)
        });

        return Object.create(this, descs);
    }
});

///////////////
// Sample Usage
///////////////

var Person = ExtendBase.extend({
  // missing: name

  // A person can tell you its name.
  talk: function() {
    return "Hello, I'm " + this.name
  }
})

var WorkingPerson = Person.extend({
  // missing: name, occupation

  // A working person also tells you their occupation when they talk.
  talk: function() {
    return Person.talk.call(this) + " and I am a " + this.occupation
  }
})

var p1 = WorkingPerson.extend({ name:"Harry", occupation:"wizard" })
console.log(p1.talk()); // "Hello, I'm Harry and I am a wizard"
请在此处查看它的工作情况:


这是一种使用原型继承的方法。要查看控制台输出,请在Chrome中按F12或在FireFox中打开FireBug。Chrome将为您提供一个可深入查看的交互式对象

function monsterMaker() {
    this.type = "monster";
    this.health = 10;
}

function squeek() {
    this.name = "squeek";
    //monsterMaker.call(this); // sets properties on this
}
squeek.prototype = new monsterMaker();
squeek.prototype.constructor = monsterMaker;

var squeaker = new squeek();

console.log(squeaker);
console.log(squeaker.name);
console.log(squeaker.type);
console.log(squeaker.health);
请在此处查看它的工作情况:

以下是一些链接:

从上面的第二个MDN链接中,您可以通过新的JavaScript方式来实现ECMAScript 5,从而包括用于扩展的库和示例代码-使用控制台查看示例输出:

// Original Author:  FireFly - Jonas Höglund - ##javascript channel
// on irc.freenode.net - see THANKS File

///////////////
// Library code
///////////////

var ExtendBase = {};

Object.defineProperty(ExtendBase, 'extend', {
    enumerable: false
    , value: function(obj) {
        'use strict';

        var descs = {}
        , objectInheritCounter = 0;

        objectInheritCounter += 1;

        Object.getOwnPropertyNames(obj).forEach(function(key) {
        descs[key] = Object.getOwnPropertyDescriptor(obj, key)
        });

        return Object.create(this, descs);
    }
});

///////////////
// Sample Usage
///////////////

var Person = ExtendBase.extend({
  // missing: name

  // A person can tell you its name.
  talk: function() {
    return "Hello, I'm " + this.name
  }
})

var WorkingPerson = Person.extend({
  // missing: name, occupation

  // A working person also tells you their occupation when they talk.
  talk: function() {
    return Person.talk.call(this) + " and I am a " + this.occupation
  }
})

var p1 = WorkingPerson.extend({ name:"Harry", occupation:"wizard" })
console.log(p1.talk()); // "Hello, I'm Harry and I am a wizard"
请在此处查看它的工作情况:


JavaScipt是一种基于原型的语言。与其试图模仿经典的面向对象语言,不如屈服于原型

在这种情况下,您需要创建一个怪物原型;以及基于怪物原型的Squeek原型。然后从Squeek对象实例化一个squeaker


JavaScipt是一种基于原型的语言。与其试图模仿经典的面向对象语言,不如屈服于原型

在这种情况下,您需要创建一个怪物原型;以及基于怪物原型的Squeek原型。然后从Squeek对象实例化一个squeaker


您不能更改此引用。您不能更改此引用。@user1689607:否-Squeek是一个构造函数。返回此值不会改变任何内容。@user1689607:No-squek是一个构造函数。return这不会改变任何东西。为什么要将Monster.prototype.name设置为squek?最好将Monster的实例指定给squek的prototype。此外,您还需要修改squek.prototype的构造函数属性,因为这是squek实例将继承的属性。Squeek构造函数是bulit–in函数对象的一个实例,因此这就是它从[[Prototype]]继承的构造函数属性应该引用的内容。为什么要将Monster.Prototype.name设置为Squeek?最好将Monster的实例分配给Squeek的原型。此外,您还需要修改squek.prototype的构造函数属性,因为这是squek实例将继承的属性。Squeek构造函数是bulit–in函数对象的一个实例,因此这就是它从[[Prototype]]继承的构造函数属性应该引用的内容。Bergi:你能告诉我你为什么这样想吗?我不太清楚为什么——不是在争论,只是不知道你为什么这么说。谢谢。伯吉:你能告诉我你为什么这么想吗?我不太清楚为什么——不知道
我不是在争论,只是不知道你为什么这么说。谢谢。monsterMaker函数中不需要返回,因为调用函数已经引用了传递的对象,并且没有使用返回值。@RobG:我不知道,我认为monsterMaker支持以var monster=monsterMaker{}的形式调用是非常明智的。你说没有使用返回值,但我不认为你真的知道;您只知道squeek不使用它。调用可以传递匿名对象,但在OP的上下文中这没有多大意义。monsterMaker函数中不需要返回,因为调用函数已经引用了传递的对象,并且没有使用返回值。@RobG:我不知道,我认为monsterMaker支持被称为var monster=monsterMaker{}是非常明智的。你说没有使用返回值,但我不认为你真的知道;你只知道squeek不使用它。调用可以传递一个匿名对象,但在OP的上下文中这没有多大意义。