在我的jQuery模板标记语言(JTML)项目中,我需要一种方式将JTML模板编译到JS函数,这样它们就可以如期地在任何时候转换成新的HTML标记。但这是一个严峻的问题,因为JTML代码涉及非作用域(全局)变量,在函数执行的时候,那些变量能够在渲染引擎的上下文中可用。当我编写这个项目的代码时,我能想到的唯一办法就是当一个模板需要被渲染时每次创建一个新的Function()。这样,在一定程度上违背了提前编译渲染引擎的目的。经过深思熟虑,我想是否可以通过JS的apply()功能创建出动态的作用域,预编译函数。

当你使用apply()或者call()方法去改变一个函数的执行上下文时,其实真正做的就是改变“this”的引用。this在非作用域下并没有效果,但会向函数的闭包链往上爬找到this(全局对象)。但是,如果我们有这样一个函数可以在它执行完毕前检查它自己的this上下文?如果我们创建了一个函数,在该函数执行完毕之前在前面插入有“this作用域“变量到它的局部作用域,我们就应该能够通过改变函数的上下文,简单地动态改变可用的非作用域变量了。下面的demo就是我要说的:

<!DOCTYPE HTML>
<html>
<head>
<title>Javascript Function() With Context</title>
<script type="text/javascript" src="jquery-1.4.2.js"></script>
<script type="text/javascript"> // I am a proxy for the Function() constructor that prepends
// code to copy the function's context variables into the
// function local scope so that they may dynamically changed
// at the time of execution.
// Function构造器代理。 在函数代码块头部插入复制函数的上下文变量到函数局部作用域。
function FunctionContext( sourceCode ){ // Call and return the Function() constructor. Notice
// that if the THIS is not Window, we are VAR'ing the
// context variables into the function local scope.
return(Function(
"if (this != window){" +
"for (var __i in this ){" +
"eval( 'var ' + __i + ' = this[ __i ];' );" +
"}" +
"}" +
sourceCode
));
} // -------------------------------------------------- //
// -------------------------------------------------- // // Define a function that uses a variable that is not
// defined as part of the function source code.
var saySomething = FunctionContext(
"console.log( name + ', you\\\'re looking so hot!' );"
); // -------------------------------------------------- //
// -------------------------------------------------- // // Now, execute the saySomething() method in three different
// contexts, each of which changes the name.
saySomething.apply({
name: "Tricia"
}); saySomething.apply({
name: "Vicky"
}); saySomething.apply({
name: "Erika"
}); </script>
</head>
<body>
<!--- Intentionally left blank. --->
</body>
</html>

我已经创造了这个函数FunctionContext(),实质上就是JS的Function()构造器代理。它的工作就是在代码块被传入Function构造器参数中前在头部插入一段逻辑。该逻辑检查函数的”this“上下文。如果函数的上下文不是window对象,说明它被call()或者apply()方法重写了,所有的this作用域值都被编译成函数局部作用域的变量了。任何上下文的变量在函数内部逻辑里都可以当做非作用域值了。

当我们跑上面的代码时,输出:

Tricia, you're looking so hot!
Vicky, you're looking so hot!
Erika, you're looking so hot!

正如所看,通过使用apply(),每次执行编译后的函数时,我都在改变上下文。而且,自从第一次执行复制”this“作用域变量到局部作用域,无作用于变量”name“从来不会报错。

我需要一种方式当一个函数被执行时动态改变变量为可用的。如果我单单用eval()函数,我将会失去预编译的优势。如果我仅用Function()构造器,我不能想到一个办法改变为可用变量,在没有使用已有的参数情况下(我可能甚至不知道该如何提前)。通过两个结合使用,我找到了最优雅的方式转换为可用的局部变量。

原文:http://www.bennadel.com/blog/1927-Faking-Context-In-Javascript-s-Function-Constructor.htm

翻译:用Javascript的Function构造器伪造上下文 by Ben Nadel的更多相关文章

  1. JavaScript之Function函数深入总结

    整理了JavaScript中函数Function的各种,感觉函数就是一大对象啊,各种知识点都能牵扯进来,不单单是 Function 这个本身原生的引用类型的各种用法,还包含执行环境,作用域,闭包,上下 ...

  2. [书籍翻译] 《JavaScript并发编程》第五章 使用Web Workers

    本文是我翻译<JavaScript Concurrency>书籍的第五章 使用Web Workers,该书主要以Promises.Generator.Web workers等技术来讲解Ja ...

  3. [书籍翻译] 《JavaScript并发编程》第七章 抽取并发逻辑

    本文是我翻译<JavaScript Concurrency>书籍的第七章 抽取并发逻辑,该书主要以Promises.Generator.Web workers等技术来讲解JavaScrip ...

  4. [书籍翻译] 《JavaScript并发编程》第四章 使用Generators实现惰性计算

    本文是我翻译<JavaScript Concurrency>书籍的第四章 使用Generators实现惰性计算,该书主要以Promises.Generator.Web workers等技术 ...

  5. [书籍翻译] 《JavaScript并发编程》第三章 使用Promises实现同步

    本文是我翻译<JavaScript Concurrency>书籍的第三章 使用Promises实现同步,该书主要以Promises.Generator.Web workers等技术来讲解J ...

  6. [书籍翻译] 《JavaScript并发编程》 第二章 JavaScript运行模型

    本文是我翻译<JavaScript Concurrency>书籍的第二章 JavaScript运行模型,该书主要以Promises.Generator.Web workers等技术来讲解J ...

  7. 机器指令翻译成 JavaScript —— No.5 指令变化

    上一篇,我们通过内置解释器的方案,解决任意跳转的问题.同时,也提到另一个问题:如果指令发生变化,又该如何应对. 指令自改 如果指令加载到 RAM 中,那就和普通数据一样,也是可以随意修改的.然而,对应 ...

  8. javascript执行环境(执行期上下文)详解

    javascript执行环境(执行期上下文) 当js控制器(control)进入可执行代码时,控制器会进入一个执行环境,活动的多个执行环境构成执行环境栈,最上面的是正在运行的执行环境,当控制器进入一个 ...

  9. JavaScript笔记 Function

    在JavaScript中方法由两部分组成: 方法名和方法体. JavaScript中的方法跟其他传统面向对象语言不同,它跟普通的变量没有区别,唯一不同点是它是Function对象,因此它会有一些Fun ...

随机推荐

  1. [javascript|基本概念]学习笔记

    1/语法 a.区分大小写 b.标识符(首字符必须是字母/"_"/"$",其他可为字母/"_"/"$"/数字,不能用关键字 ...

  2. jQuery checkBox 全选的例子

    表单处理时经常会有全选的功能,但是这个功能往往会被忽视一个细节,就是逐个选中 checkBox 直至全选时,经常会忘记修改全选 checkBox 的状态,某知名互联网公司的网盘就会出现这样的问题,问题 ...

  3. CentOS 7.2 无法生成 coredump文件

    CentOS版本 cat /etc/centos-release  CentOS Linux release 7.2.1511 (Core) 设置ulimit -c ulimited 依旧无法生成co ...

  4. Java应用短信猫

    首先确定短信猫正常连接到主机,并安装SIM卡.先用超级终端测试短息猫能不能用.安装minicom:#sudo apt-get install minicom安装完成后,执行#sudo minicom ...

  5. jQuery Mobile 开发中常见的问题

    目录 页面缩放显示问题 页面跳转后样式丢失js失效 跳转时重复调用pageinit方法的解决办法 如何调用loading效果   1页面缩放显示问题 问题描述: 页面似乎被缩小了,屏幕太宽了. 解决办 ...

  6. DevExpress控件水印文字提示

    ButtonEdit.Properties.NullValuePrompt = "提示"; ButtonEdit.Properties.NullValuePromptShowFor ...

  7. silverlight 跳转指定的aspx页面

    1.在xaml.cs中直接访问.并传递参数 System.Windows.Browser.HtmlPage.Window.Navigate(new Uri(HtmlPage.Document.Docu ...

  8. [精校版]The Swift Programming Language

    通常来说,编程语言教程中的第一个程序应该在屏幕上打印“Hello, world”.在 Swift 中,可以用一行代码实现:  println("hello, world")   如 ...

  9. [转]Oracle学习记录 九 Prc C学习

    经过前面的了解,现在想用C语言来编程了,搜索了很多东西,后来决定先用Pro C来进行学习 在安装完Oracle数据库后就可以进行编程了,里面有一个命令proc就是对程序进行预编译的. 在这记一下,这是 ...

  10. Posix 信号量

    作用 信号量的值为0或正整数,就像红灯与绿灯,用于指示当前是否可以接受任务. 信号量对进程和线程都适用. gcc编译时需加-lpthread 基本函数 信号量的相关函数与标准文件函数非常相似,可以理解 ...