2009-02-20 5 views
1

У меня есть следующие:Как я могу ссылаться на объект внутри одной из его функций-членов?

var o = {f: function(fn) { 
    fn.call(o); 
}}; 
var ob = {f: function() { 
    o.f(function() { 
     this.x = 2; //HERE: how can this reference ob? 
     //ob.x = 2; 
    }); 
}}; 
ob.f(); 
ob.x; // undefined 

o.f(fn) вызовов fn где this обязан о.

ЗДЕСЬ Я хочу использовать this для доступа к ob. Однако, когда вызывается ob.f, this привязан к o. JQuery работает, как это, я думаю. Например:

$(...).blah(function() { 
    this // this is bound to $(...) jquery object. 
    ... 
}; 

Что я делаю сейчас:

var Ob = function() { 
    var self = this; 
    self.f = function() { 
     o.f(function() { self.x = 2; }; 
    }; 
}; 
var ob = new Ob(); 
ob.f(); 
ob.x; // 2 

Но мне не нравится выше по стилистическим причинам:

  1. Используя оператор new звучит слишком классический ООП.
  2. Определение class Ob с использованием function не является интуитивным (по крайней мере, в начале).

Именно поэтому я пытаюсь определить ob с объектным литералом. Но я не могу найти способ ссылаться на объект ob на функцию , которая использует метод call, который устанавливает this другому объекту, кроме ob.

я могу сделать что-то вроде следующего:

var ob = {f: function() { 
    o.f(function() { 
     self.x = 2; 
    }); 
}}; 
var self = ob; 
ob.f(); 
ob.x; 

Но я не знаю, как фактор выше. Я пробовал:

function obj(o) { 
    return function() { 
     var self = o; 
     return o; 
    }(); 
} 
var ob = obj({f: function() { 
    o.f(function() { 
     self.x = 2; 
    }); 
}}); 
ob.f(); 
ob.x;// ReferenceError: self is not defined 

Итак, есть ли способ для ссылки на объект в функции внутри объекта надежно (this может, обязан что-либо в зависимости от контекста)?

ответ

1

После простого шаблона конструктора Douglas Crockfords я бы сделал конструктор-функцию, которая использует объектный литерал вместо нового. Как это:

var o = {f: function(fn) { 
    fn.call(o); 
}}; 

function obj() { 
    var me = {}; 
    me.f = function() { 
     o.f(function() { 
      me.x = 2; 
     }); 
    }; 
    return me; 
} 

var ob = obj(); 
ob.f(); 
ob.x; // 2 
+0

awesome! просто то, что я хотел! – numeric

+0

«Я» уже является глобальной переменной, например «undefined» и «NaN». Пожалуйста, используйте другое имя, чтобы сделать его менее запутанным. – some

3

В JavaScript функции являются объектами, имеющие два метода для вызова функции:

call(scope, arg1, arg2, ...); 
apply(scope, args); // args is an array of arguments to call the function with 

Первый аргумент «объем», является объект, который связан с «это» внутри функции. Таким образом, следующие примеры эквивалентны:

obj.method(1, 2, 3); 
obj.method.call(obj, 1, 2, 3); 
obj.method.apply(obj, [1, 2, 3]); 

В первом примере вы вызываете функцию, переданную в o.е() с использованием 'O' в сферу:

var o = {f: function(fn) { 
    fn.call(o); 
}}; 

Поэтому ваша функция, переданная в "Обского упоминание 'о', как это:

var ob = {f: function() { 
    o.f(function() { 
     this.x = 2; //HERE: how can this reference ob? 
     //ob.x = 2; 
    }); 
}}; 

В строке 'здесь', 'это' является фактически 'o'.

Вы можете попробовать следующее:

var ob = {f: function() { 
    var self = this; 
    o.f(function() { 
     self.x = 2; // self is ob now 
    }); 
}}; 

Или вы могли бы изменить функцию «от» взять сфера:

var o = {f: function(fn, scope) { 
    fn.call(scope || this); // Uses the given scope or this (= 'o') if no scope is provided 
}}; 

Затем вы можете передать «это» в 'Обского :

var ob = {f: function() { 
    o.f(function() { 
     this.x = 2; // 'this' will be the 'outer' this 
    }, this); // Here: this as scope 
}}; 
+0

Я пытался имитировать поведение объекта jquery с помощью o. Как я заметил в jquery, ** этот ** установлен как объект jquery сам, даже когда функция определена внутри моего объекта. Мне нравится шаблон дизайна конструктора Дугласа Крокфорда, опубликованный Magnar. – numeric

0

Вы можете сделать это без дополнительных функций, только с помощью литералов:

var o = {f: function(fn) { 
    fn.call(o); 
}}; 
var ob = {f: function() { 
    var self = this; // this == ob 
    o.f(function() { 
     self.x = 2; // self == enclosing function's this == ob 
    }); 
}}; 
ob.f(); 
assert(ob.x == 2);