内部类对象中的Javascript上下文

时间:2017-11-28 11:08:39

标签: javascript

在使用ES6之前,我们可以实例化一个"类"像这样...

var Animal = function(){}

然后......

var dog = new Animal()

"类"中的上下文将是类(实例)本身

var Animal = function( name ){

   this.name = name;

   this.getName = function(){

      // the context here (this) is the class (Animal)
      return this.name; // works well

   }

}

问题是,如果我不想污染根范围并使用子对象,以用于各种用途,那么上下文将成为保存函数的对象

var Animal = function( name ){

   this.utilities = {

      this.getName : function(){

         // the context here is the 'utilities' object so...
         return this.name // wouldn't work

      }

   }

}

当然我们总是可以使用

形式的东西
dog.utilities.getName.call(dog)

但这会有点长而且不舒服......

有没有办法创建'实用程序'对象并将上下文应用于其所有函数以指回根范围?无需每次都使用callapply? (不使用ES6的答案会很棒......)

3 个答案:

答案 0 :(得分:1)

确保this成为各种utilities函数的一种方法是使用箭头函数,因为箭头函数靠近this它们所在的位置'定义:

class Animal {
  constructor(name) {
    this.name = name;
    this.utilities = {
      getName: () => {       // This is an arrow function
        return this.name;    //
      }                      //
    };
  }
}
const dog = new Animal("dog");
console.log(dog.utilities.getName()); // "dog"

这基本上是旧var t = this;解决方案的ES2015 +版本:

function Animal(name) {
  var t = this;
  this.name = name;
  this.utilities = {
    getName() {
      return t.name;
    }
  };
}
var dog = new Animal("dog");
console.log(dog.utilities.getName()); // "dog"

在这两种情况下,这意味着您要为Animal的每个单独实例创建新的函数对象(代码将在这些对象之间共享,但对象是不同的) 。这很好,除非有{strong>批次的Animal个实例。

或者,您可以使用帮助程序将实例传递给:

const Animal = (function() {
  class Utilities {
    constructor(animal) {
      this.a = animal;
    }
    getName() {
      return this.a.name;
    }
  }
  
  class Animal {
    constructor(name) {
      this.name = name;
      this.utilities = new Utilities(this);
    }
  }
  return Animal;
})();
const dog = new Animal("dog");
console.log(dog.utilities.getName()); // "dog"

var Animal = (function() {
  function Utilities(animal) {
    this.a = animal;
  }
  Utilities.prototype.getName = function getName() {
    return this.a.name;
  };
  
  return function Animal(name) {
    this.name = name;
    this.utilities = new Utilities(this);
  }
})();
var dog = new Animal("dog");
console.log(dog.utilities.getName()); // "dog"

...它允许实用程序通过Utilities.prototype重用其功能对象。

答案 1 :(得分:1)

您可以使用以下内容:

var utilities = function (context) {
    return {
        getName: function () {
            console.log(context.name)
        }
    }
}

var Animal = function( name ){
   this.name = name
   this.utilities = utilities.call(null, this)
}

var dog = new Animal('dog')
dog.utilities.getName()

但是,如果您可以这样做:dog.getName()而不是dog.utilities.getName()那么您可能会有一个更清洁的解决方案(IMO),如下所示:

var Animal = function( name ){
   this.name = name
}

var utilities = {
    getName: function () {
        console.log(this.name)
    }
};

Object.assign(Animal.prototype, utilities)

var dog = new Animal('dog')
dog.getName()

如果有效,请告诉我。感谢。

新答案:

var UTILITIES = {
    getName: function () {
        console.log(this.self.name)
    }
}

var Animal = function (name) {
    this.name = name
    this.utilities = Object.create(UTILITIES, {
        self: {
            value: this
        }
    })
}

var dog = new Animal('dog')
dog.utilities.getName()

变体包括使用指向感兴趣实例的“自我”属性。现在,这个could看起来更直观。

答案 2 :(得分:0)

您可以使用getter方法。我发现它们对于需要格式化值的情况非常有用。这样,实用程序/逻辑只为此类所知,并且不会暴露在外部。



function Person(fname, lname) {
  var _fname = fname;
  var _lname = lname;
  
  Object.defineProperty(this, 'fullName', {
    get: function(){
      return _fname + ' ' + _lname
    }
  });
  
  Object.defineProperty(this, 'firstName', {
    get: function(){
      return _fname
    },
    set: function(value) {
      _fname = value;
    }
  });
  
  Object.defineProperty(this, 'lastName', {
    get: function(){
      return _lname
    },
    set: function(value) {
      _lname = value;
    }
  });
}

var person = new Person('hello', 'world');
console.log(person.fullName);

person.firstName = 'Hello';
console.log(person.fullName);

person.lastName = 'World'
console.log(person.fullName);