2014-10-21 3 views
0

Рассмотрим следующий класс и вызов foo метод: (jsFiddle: http://jsfiddle.net/dpvbd9LL/2/)Этот контекст внутри класса

function MyClass() { 
    this.Prop = "Hello"; 
} 

MyClass.prototype.foo = function() { 
    var self = this; 
    $("<p>" + self.Prop + "</p>").appendTo("#result"); 
} 

function sampleMethod(callback) { 
    // do magic stuff 
    callback(); 
} 

function executeMethod() { 
    var myClass = new MyClass(); 
    sampleMethod(function() { 
     myClass.foo(); 
    }); 
    sampleMethod(myClass.foo); 
} 

(function() { 
    executeMethod(); 
})(); 

Выход:

Здравствуйте

неопределенными

Как вам может видеть, есть большая разница между вызовами:

sampleMethod(function() { 
    myClass.foo(); 
}); 

sampleMethod(myClass.foo); 

Почему это происходит? Как написать класс, чтобы предотвратить такую ​​ситуацию?

+0

Какая ситуация? Единственное различие между двумя вызовами заключается в том, что вы завернули функцию класса в анонимную функцию. По существу это не имеет никакого значения (по крайней мере, если вы ничего не возвращаете) ... – somethinghere

+0

@somethinghere see my edit: Я вставил результат из jsFiddle. –

+0

О, это просто потому, что вы еще не создали метод. Определение метода не выполняет его. Вам нужно попробовать 'var test = new MyClass()', а затем передать sampleMethod 'test.foo'. – somethinghere

ответ

0

Это связано с тем, что sampleMethod (myClass.foo); передайте функцию myClass, но не в контексте класса, если вы протестируете текущий объект, вы увидите, что это окно, глобальное.

Если вы объявите sampleMethod в контексте объекта, вы можете сделать что-то подобное.

+0

Итак, я не могу ничего сделать в определении класса, чтобы предотвратить эту ситуацию? Я работаю в C#, поэтому функция передачи таким образом сохраняет контекст экземпляра. Это странно для меня, потому что это похоже на 'sampleMethod (myClass.foo)' Я только что прошёл «тело» функции (без экземпляра объекта, на который он был вызван) правильно? –

+0

Декларация не является строгой в JS ... Не могли бы вы дать больше информации об использовании, которое вы хотите? Вы правы, он просто передает тело функции. – Loenix

+0

Хорошо, причина использования была просто ... меньше кода :) (простое имя функции передачи вместо создания какой-либо функции, особенно для нее), но теперь я вижу, что область потеряна. –

0

Вы можете решить эту проблему, передавая родительскую сферу анонимному функции палача, как это:

function sampleMethod(callback, scope) { 
    if(scope) scope[callback](); 
    else callback(); 
} 

function executeMethod() { 
    var myClass = new MyClass(); 
    sampleMethod(function() { 
     myClass.foo(); 
    }); 
    sampleMethod("foo", myClass); 
} 

Проблема заключается в том, что вы пытаетесь передать функции от -для sampleMethod- unexisting области. Поэтому, если вы пройдете оба, вы можете называть их так, как вам нужно.

+1

Он также мог бы сделать (в чистом виде): function sampleMethod (callback, scope) { scope.callback = callback; scope.callback(); } Это решение часто используется для использования функции в области объекта. – Loenix

+1

способ более чистого использования использует 'call', как этот' callback.call (scope); ' –

+0

@King King - с' callback.call (scope) 'может область быть неопределенной 'или' false '? В противном случае нам все равно понадобилось бы утверждение if, прекратив упрощение. В противном случае, все замечательные предложения! – somethinghere