JavaScript深度解析

原创 2013年12月03日 17:57:01
Copyright (2013) 郭龙仓. All Rights Reserved.

变量声明与表达式(declarations and expressions)

代码示例:

var a; // declaration
var a = 2; // declaration and expression
var func1 = function(){ alert(3) }; // declaration and expression
function 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(){}


下面这段话可能有助于你理解变量声明与表达式的区别:

  1. Anything to the right of an = sign (or : on object literals).
  2. Anything in braces ().
  3. 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)来维护执行上下文。


图1 Environment Record
图1 Environment Record


图2 Lexical Environment
图2 Lexical Environment

图3 Execution Context
图3 Execution Context

执行上下文由三个部分组成:

  • 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引擎做了下面这些事情:

  1. 创建一个空的Object对象
  2. 将这个Object对象的原型设置为Dog
  3. 准备执行Dog函数,并用这个Object作为this参数,字符串"Jack"作为host参数
  4. 执行Dog函数
  5. 返回该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深度解析

变量声明与表达式(declarations and expressions) 代码示例: var a; // declaration var a = 2; // declaration and ex...

javascript深度解析2--this

thisthis的作用是隐式的传递一个上下文对象。使得我们的代码更加的优雅。function foo(){ console.log(this.name.toUpperCase()); }var...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

Android LayoutInflater深度解析 给你带来全新的认识

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38171465 , 本文出自:http://blog.csdn.net/lmj62...
  • wy819
  • wy819
  • 2016-05-06 15:02
  • 60

SpringMVC刘宝宝深度版

一概念:         springMVC是spring框架的一个模块,springMvc比 struts2更加高效,         spri...

[Java并发包学习八]深度剖析ConcurrentHashMap

转载----http://qifuguang.me/2015/09/10/[Java并发包学习八]深度剖析ConcurrentHashMap/ HashMap是非线程安全的,并发情况下使用,可能会...

javaScript深度解析(1)--作用域

作用域 若要转载,请著名出处。 编程语言最基本的功能就是存储变量中的值,并可以对其进行修改。为了能够存储变量,并找到它们,就需要一套严密的规则,这套规则其实就是作用域。让我们先了解一下编译原理ja...

javascript深度拷贝分析

先来介绍一下深拷贝是如何而来的。 深拷贝是对比与浅拷贝而言的,我们都知道js中分为基本类型以及引用类型,基本类型都是保存在栈里面的,而引用类型仅仅是把地址保存在栈里面,而值是存在于堆里面,浅拷贝仅仅...

深入解析JavaScript

博客核心内容:1、JavaScript中字符串的常见操作 2、JavaScript中数组的常见操作 3、JavaScript中日期的相关操作 4、JavaScript中函数的相关操作 5、Ja...

Kafka深度解析

介绍Kafka背景,使用消息系统的优势,常用消息系统对比,Kafka架构介绍,Kafka实现语义分析,Replication及Leader Election机制剖析,Consumer Group Re...

Kafka深度解析

原创文章,转载请务必将下面这段话置于文章开头处(保留超链接)。 本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/01/02/Kafka深度解析 ...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)