最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How do I wrap a function with an object in a class in javascript? - Stack Overflow

programmeradmin2浏览0评论

Let's say I have a class named Human.

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

and I have some functions for the class such as greeting and introduce. So I create them like this:

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!");
}

Since introduce and greeting can be grouped by the same category (let's name it speak), how can I simply wrap this two functions with an object? I've tried this:

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;
        }
}

Now the question is, when a function is wrapped by an object, this in the introduce function is no longer referring to the instance. So how can I work this out?

I would like to call the function as this:

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

Let's say I have a class named Human.

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

and I have some functions for the class such as greeting and introduce. So I create them like this:

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!");
}

Since introduce and greeting can be grouped by the same category (let's name it speak), how can I simply wrap this two functions with an object? I've tried this:

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;
        }
}

Now the question is, when a function is wrapped by an object, this in the introduce function is no longer referring to the instance. So how can I work this out?

I would like to call the function as this:

var eminem = new Human("Marshall Mathers", "M", 45, "aggressive");
eminem.speak.introduce();
Share Improve this question edited Mar 8, 2018 at 19:43 Roman 5,2403 gold badges24 silver badges33 bronze badges asked Nov 14, 2017 at 7:52 Johnny CheukJohnny Cheuk 2373 silver badges15 bronze badges 1
  • What's the end goal? How do you want to call the functions? – StudioTime Commented Nov 14, 2017 at 7:58
Add a ment  | 

4 Answers 4

Reset to default 5

Make Speak to A Class

Make Speak to a class, because logical grouping of variables and functionality in OOP are classes.

Speak

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

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

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

Human

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

Example

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()


An other way to solve the solution would be to use apply.

Apply

The apply() method calls a function with a given this value, and arguments provided as an array (or an array-like object).

Code

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

Example

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))

You can bind the context of this in the function in its constructor

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 way, this in your introduce function will always be the current instance of Human

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();

Based on the accepted answer you could write a few lines of code to automatically rebind all your functions using Object.keys and 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);
}

Also you could easily improve this code to not only iterate the functions of the 'speak' object.

发布评论

评论列表(0)

  1. 暂无评论