Pergunta

Dado o seguinte trecho de javascript em um escopo:

var x = 10;

function sayx() {
  alert(x);
}

sayx();

Você seria, evidentemente esperar uma impressão caixa de mensagem '10', você poderia fazer função múltipla nidificação para interagir com a forma como 'x' é determinado, porque ao resolver que x é o ambiente vai até a cadeia de escopo.

Você pode até fazer um nível de 'recompilação' com eval para injetar novos escopos em tempo de execução .. por exemplo:

var x = 10;

function sayx() {
  alert(x);
}

function wrap(f) {
  return eval('(function() { var x = 20;(' + f + ')(); })');
}

wrap(sayx)();

Isso funciona porque a função terá a sua função toString chamados que retornará a fonte 'original' .. assim, essencialmente, criar uma versão embrulhada da função que tem um novo escopo que substitui x .. o resultado será um alerta caixa que imprime '20' e não '10'.

No entanto, na superfície isso poderia aparecer para o trabalho, mas a cadeia de escopo está quebrado, o próximo item na cadeia não é mais o mesmo, porque a função 'f' é agora definida em um local diferente .. ainda pior é que a cadeia de escopo que herdou poderia conter muitas referências que a função de chamada não devem ter acesso.

Assim, há uma maneira mais apoiado, viável para injetar um item de escopo? algo como:

function withScope(f, scope) { ??? }

---

var x = 10, y = 10;

function dothemath() {
  alert(x + y);
}

var haxthemath = withScope(dothemath, { x: 9000 });
haxthemath(); // 9010 not 20

Eu estou supondo que a resposta é 'não', alguns podem argumentar há 'segurança' problemas com tal injecção escopo, mas considerando que você pode fazer o truque de qualquer maneira (embora severamente quebrado) Eu não acho que isso é ..

Os benefícios desta seria que você pode essencialmente falso suas próprias variáveis ??pseudo.

Agradecemos antecipadamente.


Editar, apenas a esclarecer um pouco, imaginar que eu queria 'withScope' uma função que tinha a seguinte cadeia de escopo:

Window - window properties
Object - { var x = 10 }
Object - { var y = 5 + x }

Eu gostaria de ser capaz de obter uma função para trás que efetivamente teve a mesma cadeia + um escopo eu fornecer .. ou seja:

withScope(somefunc, { foo: 'bar' })

Será que me

dar
Window - window properties
Object - { var x = 10 }
Object - { var y = 5 + x }
Ext scope - { foo = 'bar' }

Todas as variáveis ??de pé anteriores seria encontrada porque a minha âmbito alargado não diz nada sobre eles.

Foi útil?

Solução

Se você está se referindo por escopo para as variáveis ??locais na função e / ou o fechamento, acho que a resposta é não.

Você pode alterar o escopo da palavra-chave this usando functionName.call (escopo, arg1, ...) ou functionName.apply (escopo, [arg1, ...]); Isto poderia ser usado junto com protótipos para criar cadeias semelhantes como você descreve - se algo não é encontrada em propriedades próprias do objeto, ele olhou para cima em seu protótipo. Se a propriedade não estiver lá, o próximo protótipo na cadeia é usado e assim por diante.

Outras dicas

a resposta que eu acho que você está procurando é o construído em "com" declaração.

No entanto, eu não recomendo usá-lo, como ele é obsoleto, e muito provavelmente não existirá no ECMAScript 6

A única outra maneira eu acho que você poderia fazer esse tipo de coisa é de dentro do aplicativo host em si, manipulando o ambiente javascript do lado de fora. Ou, se você estiver usando rinoceronte, você pode realmente fazer isso a partir de javascript dentro, porque a ligação entre APIs Java e Javascript é apenas isso sem costura em rinoceronte. Quando Steve Yegge apontou pela primeira vez que fora ele explodiu minha mente. Manipular javascript do lado de fora de javascript, mas a partir de javascript dentro! É de gênio!

Se você está preso dentro de um ambiente de navegador, talvez você possa usar um interpretador de JavaScript escrito em javascript, como o narciso.

Talvez usar javascript é construído no método toString para funções?

function withScope(f, scope) {
    var toExec = "";
    for (var prop in scope) {
        toExec += "var " + prop + " = scope['" + prop + "'];"
    }
    toExec += "f = (" + f.toString() + ")";
    eval(toExec);
    return f;
}
var x = 10;
var f = function() {
    console.log(x);
};
withScope(f, {x: 20})();

Esta parece ser uma má idéia embora ...

Você se quiser brincar com o escopo que você pode apreciar a declaração let fornecidas em Javascript 1.7. versões recentes do Firefox apoio let .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top