JavaScript深度解析
来源:互联网 发布:下载床上交友软件 编辑:程序博客网 时间:2024/05/16 09:15
Copyright (2013) 郭龙仓. All Rights Reserved.
当 newDog("Jack")被调用的时候,JavaScript引擎做了下面这些事情:
任何明确声明的变量会成为Variable Object的属性,并且具备DontDelete特性。任何通过赋值的方式声明的对象属性都不具备DontDelete特性,因此可以成功delete。
另外,一些内置对象属性也具备DontDelete特性。
变量声明与表达式(declarations and expressions)
代码示例:
var a; // declarationvar a = 2; // declaration and expressionvar func1 = function(){ alert(3) }; // declaration and expressionfunction func2(){ alert(4) }; // declaration a function(function(){ alert(5) }); // expression
alert(c); // 'undefined'alert(a); // 'undefined'alert(b); // 'undefined'alert(d); // 'undefined'alert(func); // 'function func(){}'var c = a;var a =1;var b = function(){alert(2);}var d = a;;function func(){}
- Anything to the right of an = sign (or : on object literals).
- Anything in braces ().
- Parameters to functions (this is actually already covered by 2).
变量声明的结果是创建一个标识符,表达式的结果是生成一个值或者对象。
编译与执行(compilation and execution)
JavaScript代码执行分为两个阶段:
阶段一,编译(compilation)
在这个阶段代码被编译为执行树(字节码或二进制的形式,具体依赖于不同的JavaScript引擎)。
阶段二,执行(execution)
解释并执行阶段一生成的代码
编译阶段处理变量声明,执行阶段处理表达式。因此,在编译阶段完成后和执行阶段开始前,所有已声明变量的值都为undefined。
可执行代码类型(Executable Code)
JavaScript的可执行代码分为三种类型(此处就不进行代码示例了,大家可以从名字猜测每种类型所对应的代码):
- 全局代码(Global Code)
- 函数代码(Function Code)
- Eval 代码(Eval Code)
执行上下文(Execution Contexts)
每当JavaScript引擎进入一段可执行代码,就会生成一个对应的执行上下文。
在为函数代码生成执行上下文之后,JavaScript引擎还会创建一个对应的Arguments对象。
JavaScript引擎通过一个栈(Stack)来维护执行上下文。
在为函数代码生成执行上下文之后,JavaScript引擎还会创建一个对应的Arguments对象。
JavaScript引擎通过一个栈(Stack)来维护执行上下文。
图1 Environment Record
图2 Lexical Environment
图3 Execution Context
执行上下文由三个部分组成:
Lexical Environment 与 Variable Environment 均是 Lexical Environment 类型,都用来存储外部词法环境引用(outerLexicalEnvironment,请参考图2)、本地参数/本地变量(environmentRecord,请参考图2)。它们的区别在于:Variable Environment 在代码执行过程中是不变的,而 Lexical Environment 会随着代码执行进入/退出with或者catch语句块的时候动态改变(with语句块和catch语句块会引起变量环境的临时改变)。
Environment Record用来存储本地参数/本地变量。有两种类型的Environment Record存在:
一般情况下,Environment Record 是 Declarative Environment Record 类型的,但是也有少数情况下是 Object Environment Record 类型(比如浏览器环境下,window对象的属性之所以成为全局的,就是因为它的全局 Environment Record 是 Object Environment Record 类型的,还有一种情况就是 with 语句)。
- Lexical Environment(词法环境,也可以称之为Variable Object,用于构造作用域链)
- Variable Environment(变量环境,也可以称之为Activation Object, 用于存储本地变量)
- This Binding(this 绑定)
Lexical Environment 与 Variable Environment 均是 Lexical Environment 类型,都用来存储外部词法环境引用(outerLexicalEnvironment,请参考图2)、本地参数/本地变量(environmentRecord,请参考图2)。它们的区别在于:Variable Environment 在代码执行过程中是不变的,而 Lexical Environment 会随着代码执行进入/退出with或者catch语句块的时候动态改变(with语句块和catch语句块会引起变量环境的临时改变)。
Environment Record用来存储本地参数/本地变量。有两种类型的Environment Record存在:
- Declarative Environment Record
- Object Environment Record
一般情况下,Environment Record 是 Declarative Environment Record 类型的,但是也有少数情况下是 Object Environment Record 类型(比如浏览器环境下,window对象的属性之所以成为全局的,就是因为它的全局 Environment Record 是 Object Environment Record 类型的,还有一种情况就是 with 语句)。
执行上下文栈代码示例:
// 执行上下文栈(ECStack)状态变化示例/*ECStack = [ globalContext];*/ eval('var x = 10');/*eval执行上下文入栈ECStack = [ evalContext, callingContext:globalContext];*/ // eval执行上下文出栈/*ECStack = [ globalContext];*/ (function foo(){ alert(10) })();// function执行上下文入栈/*ECStack = [ <foo> functionContext, globalContext];*/ // function执行上下文出栈/*ECStack = [ globalContext];*/ (function outfool(){ function infoo1(){ alert(20) } eval('var y = 30') (function infoo2(){ alert(40) })(); return infoo1()})()(); // function执行上下文入栈/*ECStack = [ <outfool> functionContext, globalContext];*/ // eval执行上下文入栈/*ECStack = [ evalContext, callingContext:<outfool> functionContext, globalContext];*/ // eval执行上下文出栈/*ECStack = [ <outfool> functionContext, globalContext];*/ // function执行上下文入栈/*ECStack = [ <infoo2> functionContext, <outfool> functionContext, globalContext];*/ // function执行上下文出栈/*ECStack = [ <outfool> functionContext, globalContext];*/ // function执行上下文出栈/*ECStack = [ globalContext];*/ // function执行上下文入栈/*ECStack = [ <infool1> functionContext, globalContext];*/ // function执行上下文出栈/*ECStack = [ globalContext];*/
作用域链(Scope Chain)
Lexical Environment通过持有一个外部词法环境(outerLexicalEnvironment,请参考图2)的引用来形成作用域链。
闭包(Closure)
当函数B是函数A的内部函数,且函数A的返回值为函数B。那么,每调用一次函数A,并把A的返回值赋值给一个变量,就完成了一个闭包的构造。
闭包代码示例:
function buildClosure(arg1, arg2){ var localVar = 8; function innerFunc(innerArg){ return ((arg1 + arg2)/(innerArg + localVar)); } return innerFunc;} var closureVar = buildClosure(2, 4);
new 关键字做了什么?
new 代码示例:
function Dog( host ) { this.host = host;} var dog = new Dog( "Jack" );
当 newDog("Jack")被调用的时候,JavaScript引擎做了下面这些事情:
- 创建一个空的Object对象
- 将这个Object对象的原型设置为Dog
- 准备执行Dog函数,并用这个Object作为this参数,字符串"Jack"作为host参数
- 执行Dog函数
- 返回该Object对象
用不用 var 关键字有什么区别?
如果在全局作用域,用不用 var 关键字没有任何区别。
如果在局部作用域,使用 var 关键字会使JavaScript引擎创建一个局部变量,不使用 var 关键字会导致JavaScript沿着作用域链一直向上查找,直到找到该变量,如果最终没找到该变量,JavaScript引擎会在全局作用域创建该变量。
this 关键字怎么绑定的?
this值是在JavaScript引擎执行过程中动态绑定的,与源代码的位置无关,与代码执行过程有关(请参考图3)。
如果执行的是全局代码,那么this指向的是全局对象。如果执行的是函数代码,那么this指向的则是函数的调用者。如果执行的是Eval代码,那么默认情况下this的值与Eval代码外部环境中this的值一致(除非你在执行Eval代码的时候通过参数明确指定eval的执行上下文)。
以下方法可以修改默认的this值:
- Function.prototype.apply( thisArg, argArray )
- Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
- Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
- Array.prototype.every( callbackfn [ , thisArg ] )
- Array.prototype.some( callbackfn [ , thisArg ] )
- Array.prototype.forEach( callbackfn [ , thisArg ] )
- Array.prototype.map( callbackfn [ , thisArg ] )
- Array.prototype.filter( callbackfn [ , thisArg ] )
delete 为什么会返回 false ?
JavaScript的对象属性具有(Property)一些特性(Attribute),包括DontDelete特性。具有DontDelete特性的属性在使用delete删除的时候会返回false。任何明确声明的变量会成为Variable Object的属性,并且具备DontDelete特性。任何通过赋值的方式声明的对象属性都不具备DontDelete特性,因此可以成功delete。
另外,一些内置对象属性也具备DontDelete特性。
- JavaScript深度解析
- javascript深度解析2--this
- javaScript深度解析(1)--作用域
- JavaScript的this指向问题深度解析
- JavaScript的this指向问题深度解析
- JavaScript 的 this 指向问题深度解析
- JavaScript 的 this 指向问题深度解析
- java web之javascript深度解析(上)
- 深入了解webkit内核第一篇:JavaScript引擎深度解析
- 深入了解webkit内核第一篇:JavaScript引擎深度解析
- JavaScript学习笔记8-jQuery基本选择器深度解析
- JavaScript学习笔记8-jQuery层次选择器深度解析
- JavaScript学习笔记8-jQuery基本过滤选择器深度解析
- JavaScript中对象进行深度clone,url参数解析
- 深入理解webkit内核系列第二篇:JavaScript引擎深度解析
- JavaScript学习笔记8-jQuery内容过滤选择器、可见性过滤选择器深度解析
- JavaScript学习笔记8-jQuery属性过滤选择器、子元素过滤选择器深度解析
- 深度解析公用计算
- 布局方式(边界布局)
- Android webview goback 使用cache中的网页
- Javascript中最常用的55个经典技巧
- asp.net mvc 3 session失效 出现画中画
- C# 读写 excel (它支持html格式的excel文件)
- JavaScript深度解析
- asp.net mvc 清除视图缓存
- sql server 表字段查询
- Summary
- 实例化spring容器applicationContext的几种方法
- 最牛B的编码套路
- Apache+Tomcat关于Session Sticky的负载均衡
- javascript新的原生态API
- jsp的防注入代码