2

我一直在尝试各种方法来模拟 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),但是有没有办法使用左手赋值或解决方法以这种方式更改新创建的对象,不使用额外的库?

4

5 回答 5

1

这是一种使用原型继承的方法,. 要查看控制台输出,请在 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);

在这里看到它的工作:

http://www.quirkscode.com/flat/forumPosts/extendThis/extendThis.html

以下是一些链接:

https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Inheritance_and_the_prototype_chain

https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Inheritance_Revisited

从上面的第二个 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"

在这里看到它的工作:

http://www.quirkscode.com/flat/JSLearning/src/extend/extend.html

于 2012-10-01T22:25:41.533 回答
1

您不能分配给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 是按值传递的,但这种情况下的“值”是整个this对象,所以在某些方面它就像按引用传递。)

于 2012-10-01T21:28:15.717 回答
1

不,您不能分配给this. 但是,您不需要!只需将实例 ( this)传递给monsterMaker,该函数就会为其添加一些属性 - 这正是您想要的。您不需要返回对象,或使用返回的对象 - 它仍然是this.

function Squeek() {
    this.name = "squeek";
    monsterMaker(this);
}

new Squeek(); // will have type and health
于 2012-10-01T21:28:23.923 回答
1

你应该试试:

var squeaker = new squeek();

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

function squeek() {
    this.name = "squeek";
    monsterMaker.call(this);
}

这样,您可以使用 monsterMaker 函数的属性“装饰”您想要的任何对象。

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

于 2012-10-01T21:37:08.977 回答
0

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

在这种情况下,您要创建一个Monster原型;以及Squeek基于原型的Monster原型。然后squeakerSqueek对象实例化 a 。

/* Set up your Monster prototype */
function Monster() { /* constructor */}
Monster.prototype.type = "monster";
Monster.prototype.health = 10;

/* Now use the prototype of a Monster to create the prototype of a Squeek */
function Squeek() { /* constructor */ }
Squeek.prototype = new Monster(); // thanks Bergi and RobG
Squeek.prototype.constructor = Squeek; // thanks RobG
Squeek.prototype.name = "squeek";

/* Now let's instantiate a Squeek */
var squeaker = new Squeek();
console.log(squeaker.name); // squeek
console.log(squeaker.type); // monster
console.log(squeaker.health); // 10
console.log(squeaker.constructor === Squeek); // true

var monster = new Monster();
console.log(monster.name); // undefined
于 2012-10-01T22:27:17.320 回答