До использования 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 был бы замечательным...)
Один из способов гарантировать, что 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"
Это в основном версия ES2015+ старого var t = this;
решение:
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
(код будет разделяться между этими объектами, но объекты разные). Это прекрасно, если не будет много экземпляров 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
.
bind
. Я обновлю.
Вероятно, вы можете использовать следующее:
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
выглядеть более интуитивно.
this.utilities = utilities.call(null, this)
или, вы знаете, this.utilities = utilities(this)
(что в точности то же самое).
Вы можете использовать методы геттера. Я считаю их очень полезными для случаев, когда мне требуется форматированное значение. Таким образом, утилиты/логика известны только этому классу и не отображаются снаружи.
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);
this
не "контекст".this
именноthis
, что фактически является просто аргументом специальной функции. Во-вторых,this
не относится к классу (например, функции конструктора), это относится к экземпляру (объекту), созданномуnew
.