在使用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)
但这会有点长而且不舒服......
有没有办法创建'实用程序'对象并将上下文应用于其所有函数以指回根范围?无需每次都使用call
和apply
? (不使用ES6的答案会很棒......)
答案 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);