Обозначение в квадратных скобках Javascript Несколько динамических свойств - PullRequest
2 голосов
/ 22 августа 2011

Это может звучать немного необычно, мне никогда раньше не приходилось так использовать обозначения в квадратных скобках, и, ломая себе голову, я не могу придумать, как добиться желаемого результата.

Я реализую оболочку обратного вызова, чтобы поддерживать ссылку this при передаче методов в качестве обратных вызовов

например.

foo.prototype.wrap = function(name){
    var wrapper,
        self = this;

    wrapper = function(){
        self[name](arguments);
    };

    return wrapper;
};

// usage

foo.wrap('bar');

// executes foo.bar maintaining 'this' as a reference to foo 

У меня проблема в том, что у foo есть несколько вложенных методов

, например

foo.bar.close();

Я пытаюсь найти способ заставить метод обертки поддерживать вложенные методы

, например * * 1016

foo.wrap('bar.close')

// or

foo.wrap('bar','close');

Таким образом, функция foo.wrap должна динамически добавлять квадратные скобки, соответствующие длине или переданным аргументам.

, например

self[x][y][z](arguments);

Я не могу придумать, как это сделать. Есть идеи ?

У меня есть скрытое подозрение, что это невозможно, хотя.

Ответы [ 2 ]

5 голосов
/ 23 августа 2011

У меня, должно быть, один из тех дней, когда ты все забываешь :)

Хотя ответ @ NilColor верен, и я знал это, я просто не думал, что надену правильную шляпу.

В любом случае, я решил, что мне все еще нравится идея иметь обертку, которая требует немного меньшей специфичности, когда вы прикрепляете ее к своим объектам. И немного менее многословен.

Итак, я написал это вместе со своим оригинальным мышлением, вам это может понравиться.

myObj.wrap = function(path, context){ 
    var wrapper,
        method = ( typeof path != 'string' && context )? path : this,
        context =  (typeof path === 'object' && context === undefined)? 
            path : (context || this);

    if (typeof path === 'string'){
        path = path.split('.');

        for ( var i = 0; i < path.length; i++ ){
            method = method[path[i]];
            if ( context === true  )
                context = ( i === path.length - 2 )? method : context; 
        };
    };

    wrapper = function(){
        method.apply(context, arguments);
    };

    return wrapper;
}

использование:

Привязать любое количество вложенных методов к myObj

    myObj.wrap('foo') //binds myObj.foo to myObj

// or

    myObj.wrap('foo.bar') //binds myObj.foo.bar to myObj

//or if myObj is a function

    myFunc.wrap() // binds myFunc to myFunc

Привязать метод myObj к другому объекту

    myObj.wrap('foo.bar', someObj) //binds myObj.foo.bar to someObj

//or if myObj is a function

    myFunc.wrap(someObj) //Binds myFunc to someObj

Привязать вложенный метод к его родителю

    myObj.wrap('foo.bar', true) // binds myObj.foo.bar to myObj.foo

Использовать в качестве помощника

    myObj.wrap(someFunc, someObj) //binds someFunc to someObj

Если вы ищете ответ на исходный вопрос не в контексте привязки метода.

myObj.getProps = function(path, context){
var context = context || this;
    path = path.split('.');


for ( var i = 0; i < path.length; i++ ){
            context = context[path[i]];
    };

    return context;
};

Использование:

прикрепить к объекту или как отдельную функцию

Получить свойства

myObj.getProps('foo.bar') // returns mayObj.foo.bar

Дайте ему контекстный объект

myObj.getProps('user.name', myAccounts) // returns myAccounts.user.name

для использования в качестве автономной функции замените

myObj.getProps = function(path,context){....}

с

function getProps(path,context){....}

Примечание

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

например.

getProps('myObj.foo.bar')

Вы все еще можете использовать контекстный селектор для изменения ссылочного объекта.

3 голосов
/ 22 августа 2011

Общая концепция «связывания» this выглядит примерно так:

function bind(method, context) {
      var args = Array.prototype.slice.call(arguments, 2);
      return function() {
            var a = args.concat(
                               Array.prototype.slice.call(arguments, 0));
            return method.apply(context, a);
      }
}

Таким образом, вы получите ссылку на method со ссылкой this (context). Таким образом, вы можете связать вложенные методы следующим образом:

> foo = {}
> foo.a = function(){console.log('a'); console.log(this)}
> bar = {bar: 'yeah'}
> f = bind(foo.a, bar)
> f()
-> a
-> {bar: 'yeah', __proto__: Object}

Это то, что вы ищете?

...