如何在javascript中用类中的对象包装函数?

时间:2017-11-14 07:52:17

标签: javascript function oop object javascript-objects

我们说我有一个名为Human的课程。

function Human(name, gender, age, personality){
    this.name = name;
    this.gender = gender;
    this.age = age;
    this.personality = personality; 
}

我有一些类的功能,例如greetingintroduce。所以我像这样创建它们:

Human.prototype.introduce = function() {
    var _gender = {"M": "Boy", "F": "Girl"};
    switch(this.personality)
    {
    case "passionate":
        alert("Hi, how are you? My name is " + this.name + ". I'm " + this.age + " years old " + _gender[this.gender] + ". ");
        break;
    case "aggressive":
        alert("I'm " + this.name + ". What you want? ");
        break;
    }
}

Human.prototype.greeting = function() {
    alert("Hi!");
}

由于introducegreeting可以按相同的类别进行分组(让我们将其命名为speak),我怎样才能简单地用对象包装这两个函数?我试过这个:

Human.prototype.speak = {};
Human.prototype.speak.greeting = function(){
    alert("Hi!");
}
Human.prototype.speak.introduce = function(){
var _gender = {"M": "Boy", "F": "Girl"};
        switch(this.personality)
        {
        case "passionate":
            alert("Hi, how are you? My name is " + this.name + ". I'm " + this.age + " years old " + _gender[this.gender] + ". ");
            break;
        case "aggressive":
            alert("I'm " + this.name + ". What you want? ");
            break;
        }
}

现在的问题是,当一个函数被一个对象包装时,introduction函数中的this不再引用该实例。那么我该如何解决这个问题呢?

我想把这个函数称为:

var eminem = new Human("Marshall Mathers", "M", 45, "aggressive");
eminem.speak.introduce();

4 个答案:

答案 0 :(得分:5)

与A级人员交谈

使Speak成为一个类,因为OOP中的变量和功能的逻辑分组是类。

在线

function Speak(human) {
    this.human = human
}

Speak.prototype.greeting = function () {
    // ...
}

Speak.prototype.introduce = function () {
    // ..
}

function Human(name, gender, age, personality, greetWord) {
    this.name = name;
    this.gender = gender;
    this.age = age;
    this.personality = personality;
    this.speak  = new Speak(this)
}

实施例



function Human(name, gender, age, personality, greetWord) {
    this.name = name;
    this.gender = gender;
    this.age = age;
    this.personality = personality;
    this.greetWord = greetWord;
    this.speak  = new Speak(this)
}

function Speak(human) {
    this.human = human
}

Speak.prototype.greeting = function () {
    alert(this.human.greetWord + "!");
}

Speak.prototype.introduce = function () {
    var _gender = { "M": "Boy", "F": "Girl" };
    switch (this.human.personality) {
        case "passionate":
            alert("Hi, how are you? My name is " + this.human.name + ". I'm " + this.human.age + " years old " + _gender[this.human.gender] + ". ");
            break;
        case "aggressive":
            alert("I'm " + this.human.name + ". What you want? ");
            break;
    }
}

var peter = new Human('Peter', 'M', 35, 'aggressive', 'Hi')
peter.speak.greeting()
peter.speak.introduce()




解决方案的另一种方法是使用apply。

Apply

  

apply()方法调用具有给定值的函数,并将参数作为数组(或类数组对象)提供。

代码

var peter = new Human('Peter', 'M', 35, 'aggressive')
console.log(peter.speak.introduce.apply(peter))

实施例



function Human(name, gender, age, personality){
    this.name = name;
    this.gender = gender;
    this.age = age;
    this.personality = personality; 
}

Human.prototype.speak = {};
Human.prototype.speak.greeting = function(){
    alert("Hi!");
}
Human.prototype.speak.introduce = function(){
var _gender = {"M": "Boy", "F": "Girl"};
        switch(this.personality)
        {
        case "passionate":
            alert("Hi, how are you? My name is " + this.name + ". I'm " + this.age + " years old " + _gender[this.gender] + ". ");
            break;
        case "aggressive":
            alert("I'm " + this.name + ". What you want? ");
            break;
        }
}

var peter = new Human('Peter', 'M', 35, 'aggressive')
console.log(peter.speak.introduce.apply(peter))




答案 1 :(得分:3)

您可以bind在其构造函数

中的函数中this的上下文
function Human(name, gender, age, personality){
    this.name = name;
    this.gender = gender;
    this.age = age;
    this.personality = personality;
    this.speak.introduce = this.speak.introduce.bind(this);
}

这样,this函数中的introduce将始终是Human的当前实例

答案 2 :(得分:1)

function Human(name, gender, age, personality){

    this.name = name;
    this.gender = gender;
    this.age = age;
    this.personality = personality; 

    var self = this; //this is how

    this.speak = {

        introduce: function() {

            var _gender = {"M": "Boy", "F": "Girl"};
            switch(self.personality)
            {
            case "passionate":
                alert("Hi, how are you? My name is " + self.name + ". I'm " + self.age + " years old " + _gender[self.gender] + ". ");
                break;
            case "aggressive":
                alert("I'm " + self.name + ". What you want? ");
                break;
            }
        },

        greeting: function() {

            alert("Hi!");
        }
    };
}

var hulk = new Human("Hulk", "M", 33, "aggressive");
hulk.speak.introduce();

答案 3 :(得分:1)

根据接受的答案,您可以编写几行代码,使用Object.keys和forEach自动重新绑定所有函数。

function Human(name, gender, age, personality){
    this.name = name;
    this.gender = gender;
    this.age = age;
    this.personality = personality; 

    Object.keys(this.speak).filter(function(key) {
        return typeof this.speak[key] === 'function';
    }, this).forEach(function(key) {
        this.speak[key] = this.speak[key].bind(this);
    }, this);
}

此外,您可以轻松改进此代码,不仅可以迭代“说话”的功能。对象