2012-04-05 2 views
2

Меня не интересует звонок или применяется для изменения ссылки this. Только для моих собственных интересов я играю с идеей для другого, требующего техники для javascript, который бы сделал для некоторых более чистых определений, и цель заключалась в том, чтобы не передавать массивы или дублировать имена ссылочных модулей для моих определений.Изменение области видимости функции в Javascript

У меня есть образец решения (просто доказательство концепции) с использованием toString и eval для функции, но мне интересно, есть ли более безопасный или эффективный способ сделать это.

// Sample module libraries (would probably be in their own files) 
someModules = { 
    testModule: {test: function(){console.log("test from someModule")}}, 
    anotherModule: { doStuff: function(){console.log("Doin stuffs!");}} 
}; 

sampleRequire = function() { 

    // Load the modules 
    for (var i=arguments.length-2; i>=0; --i){ 

     // Create a local variable reference to the module 
     eval ('var '+arguments[i]+' = someModules.'+arguments[i].toString()); 
    } 

    // Redefine the programmer's function so that it has my local vars in its scope 
    eval("var fn = "+arguments[arguments.length-1]); 

    return fn; 
} 

// Main code... 
sampleRequire('testModule', 'anotherModule', 
    function(){ 
     testModule.test(); 
     anotherModule.doStuff(); 
    } 
)(); 

Edit:

Pointy сделал отличную точку, что это будет полностью уничтожить сферу основной функции, которая часто раз быть неприемлемым. В идеале я хотел бы видеть, что переменные модуля добавляются в область функции, не сбивая другие переменные с областью (за исключением имен модулей - программист должен знать, что нельзя использовать одно и то же имя для двух вещей). Я уверен, что это, вероятно, невозможно, но я все равно буду любить некоторые идеи.

Другая цель - сделать это гибко, не добавляя аргументы на модуль к основной функции. В противном случае мы вернемся к квадрату с стилями CommonJS (которые я не пытаюсь сражаться, просто интересуюсь областью!).

+0

Хорошо, если вы не заинтересованы в вызове или подаете заявку и предпочитаете использовать противный eval, это ваш выбор, он будет работать, но вы никогда не получите от этого никакого результата, и если вы это сделаете, возможно, вы заслужили порку. Редактировать: просто шутка не воспринимает это плохо. Но после многих лет развития я часто говорю: «Это не потому, что мы можем это сделать» – elmuchacho

+2

Если код в «someModules» сам был записан, чтобы иметь другие локальные переменные в области закрытия, ваш подход полностью их сломает. – Pointy

+0

Без обид! Весь этот вопрос действительно предназначен для развлечений и экспериментов. Но применять и звонить не решают проблему. – andyortlieb

ответ

1

я склонен сказать «вы делаете это неправильно». Использование необъявленных переменных никогда не является хорошей идеей, хотя вы можете.

Вот еще один хак, который записывает модули в глобальный объект. Однако это может иметь побочные эффекты для методов, вызванных основной функцией.

sampleRequire = function() { 

    var cache = {}; 
    var moduleNames = [].slice.call(arguments); 
    var fn = moduleNames.pop(); 

    return function() { 
     var result, name, i; 
     // export modules to global object 
     for (i = 0; i < moduleNames.length; i++) { 
      name = moduleNames[i]; 
      cache[name] = window[name]; // remember old values 
      window[name] = someModules[name]; 
     } 
     result = fn.apply(null, arguments); 
     // restore original global stuff 
     for (i = 0; i < moduleNames.length; i++) { 
      name = moduleNames[i]; 
      window[name] = cache[name]; 
     } 
     return result; 
    }; 
} 

Я также попытался немного магии с with ключевым словом, которое было в основном сделано для именно то, что вы хотите. Однако, похоже, что в этом случае он не работает без eval.

0

Я не могу думать о другом способе делать то, что вам нужно. Я также подозреваю, что это может быть одним из немногих вариантов использования eval, который не является злом. Но имейте в виду, что модули могут полагаться на свои области, и это может сломать их.

+1

О, я все еще думаю, что это зло. – andyortlieb

0

Как о чем-то вроде:

someModules = { 
    testModule: {test: function(){console.log("test from someModule")}}, 
    anotherModule: { doStuff: function(){console.log("Doin stuffs!");}} 
}; 

function requireModules() { 
    var all = []; 
    for (var i = 0, l = arguments.length; i<l; i++) { 
    all.push(someModules[i]); 
    } 
    return all; 
} 

(function(testModule,anotherModule){ 
    testModule.test(); 
    anotherModule.doStuff(); 
}).apply(null,requireModules('testModule','anotherModule')); 
+0

'window' - это только глобальный объект в браузерах. В узле.js, например, глобальный объект является «глобальным». В веб-работниках глобальный объект «сам». –

+0

@RobW, ты совершенно прав - я хотел передать это. – Benjie

+1

Я согласен с подходом. Однако прочитайте первую строчку в вопросе;) –

Смежные вопросы