#javascript
#javascript
Вопрос:
Я изучаю Javascript
и учусь, как использовать call
. Я создал этот скрипт, и я не знаю, почему у меня не может быть доступа к этой переменной Time
.
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {});
var myNewObj = new MyObject.Runner(1000); myNewObj.newTest('1', function() {
console.log(this.time) //output: undefined
});
Итак, как я могу получить значение времени внутри newTest
функции?
Комментарии:
1. Я немного сбит с толку. В вашей
newTest
функции вы нажимаетеexecute
на массив, но он не вызывается. Также альтернативным вариантом является использованиеexecute.bind(this)
вместоfunction(){ execute.call(this) }
2. Анонимная функция
this
ссылается наwindow
. Попробуйте выполнитьfunction() { console.log(this.time); }.bind(this)
3. @AndrewLi Нет.
this
указывает на временную функцию,test
поскольку OP использует.call(this)
внутриtest
Ответ №1:
Проблема в newTest
функции
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
Здесь this
указано на test
, а не Runner
. Вам нужно будет сохранить контекст в переменной, а затем установить его в call.
Runner.prototype.newTest = function(index, execute) {
var self = this;
var test = function() {
return execute.call(self);
}
myFunctionArray.push(test);
}
.call self
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
var self = this;
var test = function() {
return execute.call(self);
}
myFunctionArray.push(test);
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {}));
var myNewObj = new MyObject.Runner(1000);
myNewObj.newTest('1', function() {
console.log(this, this.time) //output: undefined
});
myNewObj.execute()
.bind
Как указано, вы даже можете использовать .bind
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
myFunctionArray.push(execute.bind(this));
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {}));
var myNewObj = new MyObject.Runner(1000);
myNewObj.newTest('1', function() {
console.log(this, this.time) //output: undefined
});
myNewObj.execute()
Комментарии:
1. Спасибо! Теперь все работает нормально!
2. Просто указатель,
(MyObject|| (MyObject= {})
должен быть(MyObject || {})
Ответ №2:
Когда вы объявляете свою функцию Runner, вы фактически объявляете функцию, которая не принимает аргументов, которая затем сама объявляет функцию с именем Runner, которая принимает один аргумент.
Ответ №3:
На самом деле в этом фрагменте кода :
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
это будет ссылаться на тестовую переменную (согласно шаблону вызова конструктора)
Итак, чтобы передать правильную переменную, кэшируйте значение this в другой переменной, а затем передайте это функции.