JavaScript. The core.

1.对象

2.原型链

3.构造函数

4.执行上下文堆栈

5.执行上下文

6.变量对象

7.活动对象

8.作用域链

9.闭包

10.this值

11.总结

这篇文章是“ECMA-262-3 in detail”系列的一个摘要和总结。每一部分包含了对应章节的连接引用,所以你可以仔细去阅读得到一个更深刻的理解。适合的读者:资深程序员,专家。我们从探讨对象的概念开始,这也是ECMAScript的奠基石。

对象

ECMAScript,一个高度抽象的面向对象语言。它按原始方式处理对象,但当我们需要时,它也可以转化对象。

对象是只有一个原型对象的属性集合。这个原型是object或者null

让我们看一个对象的基本实例,对象的原型是通过内置属性[[Prototype]]引用的。然而专门为了理解原型对象,在图中我们将会用_<internal-property>_下划线_proto_代替双括号。代码:

 var foo={
x:10,
y:20
};
  我们有了含有两个显式的自身属性和一个隐式的_proto_属性的结构,这个_proto_属性是foo原型的一个引用:

                                     图1.一个含有原型的基本对象

这些原型需要什么?让我们思考完原型链的概念后来回答这个问题。

原型链

原型对象也仅仅是一个简单的对象,且他们也有自己的原型。如果一个原型对象有一个非null的引用指向它的原型,这样循环下去(译者注:到null终止)。这就形成所谓的原型链。

     原型链是一个有限长的对象链,用来实现继承和共享属性的。

考虑这种情况,当我们有两个仅仅只在一些小的部分存在差异而其他绝大部分都相同的对象。为了设计一个更好的系统,很明显的,在单一的对象中我们会重用相似功能/代码,而不用去重复它。在基于类的系统中,这种代码重用方式叫基于类的继承-你把相似的功能放在类A中,然后构造从类A继承而来的类B和类C,他们都有自身的微小变化。

ECMAScript没有类的概念,然而代码重用方式也没有太大不同(尽管在某些方面它比基于类的方式更灵活),是通过原型链来实现代码重用的。这种继承被称为仿类继承(或者为了符合ECMAScript,叫原型链继承)。

类似在例子中用classesA,B和C。在ECMAScript中,你可以创建对象:a,b和c。所以对象a含有对象b和c的相同部分。b和c仅仅包含他们自身的属性或者方法。

 var a={
x:10,
calculate:function(z){
return this.x+this.y+z
}
};
var b={
y:20,
_proto_:a
};
var c={
y:30,
_proto_:a
};
//调用继承的方法
b.calculate(30);//
c.calculate(40);//

很简单吧。我们发现b和c获取了定义在对象a中的calculate方法。准确的说是通过原型链获取的。

原理很简单:如果一个属性或者方法在对象自身中找不到(也就是说对象中没有一个这样的自身属性),然后就试图在原型链中寻找这个属性/方法。如果这个属性 在原型中没有找到,则考虑到这个原型对象的原型中查找,递推下去,也就是说贯穿整个原型链(在基于类的继承中是完全一样的,在解析一个继承的方法时-遍历 整个类链)。第一个找到的同名属性/方法被使用。所以,被找到的属性被称为继承属性。如果遍历完整个原型链,这个属性还是没找到,返回 undefined。

注意,在使用继承方法时,方法中的this值被设置为初始对象(译者注:调用对象),而不是方法存在的原型对象。也就是说,在上面例子中的this.y是从b和c获取的,而不是从a获取。然而,this.x是通过原型链机制从a中获取。

如果一个对象没有显式的定义其原型,缺省的_proto_值将指向Object.prototypeObject.prototype对象也有自身的_proto_,就是这个原型链的最终连接,其值为null。下面这幅图展示了a,b和c对象的继承结构:

图2.原型链

注意:ES5中标准化了一个基于原型继承的替代方法Object.create函数:

 var b=Object.create(a,{y:{value:20}});
var c=Object.create(a,{y:{value:30}});

ES6中标准化了__proto__,可以在对象初始化时使用

经常需要得到有相同或者类似结构(也就是有相同的属性集合),而其值又不同的一些对象。在这种情况下我们应该使用构造函数在特定模式下来创建对象。

构造函数

除了通过特定模式创建对象之外,构造函数还干了另外一件有用的事情-为新创建的对象自动设置一个原型对象。这个原型对象放在ConstructorFunction.prototype的属性中。例如我们用构造函数重写前面例子中的b和c,因此,对象Foo.prototype扮演着a(原型)的角色:

 //一个构造函数
function Foo(y){
//将会通过特定模式创建对象:他们会创建自身的"y"属性
this.y=y;
}
//"Foo.prototype"存放着新构建对象的原型引用。因此我们可以用它来定义共享/继承的属性和方法。和前面的例子一样,我们有:
//可继承属性"x"
Foo.prototype.x=10;
//可继承方法"calculate"
Foo.prototype.calculate=function(z){
return this.y+this.x+z;
};
//使用"pattern"Foo来创建我们的b,c对象
var b=new Foo(20);
var c=new Foo(30);
//调用继承的方法
b.calculate(30);//
c.calculate(40);//
//我们展示所期望的引用属性
console.log(
b._proto_===Foo.prototype,//true
c._proto_===Foo.prototype,//true
//"Foo.prototype"自动构造了特殊的"constructor"属性,它是构造函数自身的引用;实例b和c可以通过委托和检测他的构造函数来找到她
b.constructor===Foo,//true
c.constructor===Foo,//true
Foo.prototype.constructor===Foo,//true
b.calculate===b._proto_.calculate,//true
b.__proto__.calculate === Foo.prototype.calculate//true
);

这段代码可以用如下的关系图表示:

图3.构造函数和对象之间的关系

上图再一次表明每一个对象都有一个原型。构造函数的_proto_Function.prototype,通过它(译者注:Function.prototype)的 _proto_属性再次引用到Object.prototype。再次重申,Foo.prototype仅仅只是Foo的一个显式属性指向b和c对象的原型。

   这个主题的完整和详细的解释在这个系列的第七节能找到。这里你会找到不同OOP语言的范例和理论以及和ECMAScript的比较。Chapter 7.2. OOP. ECMAScript implementation致力于ECMAScript的OOP。

现在,我们了解了对象的基础知识,然我们看看在ECMAScript中代码执行时如何实现的。这就是所谓的执行上下文堆栈,这里面的每一部分也可以抽象的表示为一个对象。是的,在ECMAScript的操作中处处充斥着对象的理念。

执行上下文堆栈

有三种类型的ECMAScript代码:全局代码,函数代码和eval代码。每一种代码都在其执行上下文中运行。只有一个全局上下文,可能有许多函数和eval执行上下文的实例。每次调用函数,进入函数的执行上下文并执行器函数代码。每次调用eval函数,进入eval的执行上下文并运行它的代码。

记住一个函数可能产生无限多个上下文环境,因为每调用一次函数(即使函数递归的调用自己)都会产生一个新的上下文:

 function foo(bar){
//调用同一个函数,由于不同的上下文状态(比如"bar"参数值)产生不同的上下文
foo(10);
foo(20);
foo(30);
}

一个执行上下文可能激活另一个上下文,例如。一个函数调用另一个函数(或者全局上下文调用全局函数),等等。逻辑上这是有一个堆栈来实现的,就是所谓的执行上下文堆栈。激活了另一个上下文的上下文叫做调用者。被激活的上下文叫做被调用者。同时被调用者也可以是其他被调用者的调用者(例如,一个函数在全局上下文调用,又调用了它的一些内部函数)。

当一个调用者激活(调用)一个被调用者,调用者暂停它的上下文并传递控制流进入被调用者。被调用者被压入栈中并成为当前(激活)的执行上下文。当被调用者 的上下文结束后,控制流回到调用者中,运行调用者的上下文处理(此时他可能有激活了其他上下文),直到结束。被调用者可能由于错误返回或调出。一个抛出二 没有没捕获的错误会跳出(从堆栈中弹出)一个或多个上下文。

例如。所有的ECMAScript程序运行时可以表示为一个执行上下文堆栈(EC),栈的顶部是一个激活上下文:

图4.一个执行上下文堆栈

程序开始时便进入全局执行上下文,栈的第一个元素也是最底部的元素。然后全局代码进行了一些初始化,创建了必要的对象和函数。在执行全局上下文时,它的代 码会激活其他(已经创建)函数,并进入到他们的执行上下文,向执行上下文堆栈汇总推入新的元素,一直下去。当初始化结束后,运行的系统会等待一些事件(例 如用户点击鼠标),这些事件会激活一些函数并进入一个新的执行上下文。

在下图中,有函数上下文EC1和全局上下文Global EC,当全局上下文进入和跳出EC1时堆栈变化如下:

图5,执行上下文堆栈变化

这准确的描述了ECMAScript中的运行程序是如何管理代码的执行的。关于ECMAScript中执行上下文更详细的信息请阅读Chapter 1. Execution context.

执行上下文

执行上下文可以抽象的表示为一个简单的对象。每一个执行上下文都有一些必要的属性(可以叫做上下文状态)去追踪它对应代码的执行进程。下图展示了一个上下文的结构:

图6一个执行上下文结构

除了这三个必须的属性(变量对象,this值和作用域链),执行上下文依据具体实现可能有其他附加状态。让我们详细的考虑上下文的这些重要属性。

javascript系列之核心知识点(一)的更多相关文章

  1. javascript系列之核心知识点(二)

    变量对象       变量对象是一个与执行上下文相关联的容器.它是一个和上下文密切结合的特殊对象,含有定义在上下文中的变量和函数声明.注意,函数表达式(和函数声明不同的)不包含在变量对象中. 变量对象 ...

  2. 【SpringBoot MQ 系列】RabbitMq 核心知识点小结

    [MQ 系列]RabbitMq 核心知识点小结 以下内容,部分取材于官方教程,部分来源网络博主的分享,如有兴趣了解更多详细的知识点,可以在本文最后的文章列表中获取原地址 RabbitMQ 是一个基于 ...

  3. javascript中的一些核心知识点以及需要注意的地方

    前言 近期杂事甚多,这些事情的积累对知识体系的提升有好处,但是却不能整理出来,也整理不出来 比如说我最近研究的Hybrid在线联调方案便过于依赖于业务,就算分享也不会有人读懂,若是抽一点来分享又意义不 ...

  4. 深入理解JavaScript系列(10):JavaScript核心(晋级高手必读篇)

    本篇是ECMA-262-3 in detail系列的一个概述(本人后续会翻译整理这些文章到本系列(第11-19章).每个章节都有一个更详细的内容链接,你可以继续读一下每个章节对应的详细内容链接进行更深 ...

  5. JavaScript核心知识点

    一.JavaScript 简介 一.JavaScript语言的介绍:JavaScript是基于对象和原型的一种动态.弱类型的脚本语言 二.JavaScript语言的组成:JavaScript是由核心语 ...

  6. 深入理解javascript系列(4):立即调用的函数表达式

    本文来自汤姆大叔 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行. 在详细了解这个之前,我们来谈了解一下“自执行”这个叫法,本文对这个功能的叫法 ...

  7. 深入理解JavaScript系列:JavaScript的构成

    此篇文章不是干货类型,也算不上概念阐述,就是简单的进行一个思路上的整理. 要了解一样东西或者完成一件事情,首要的就是先要搞清楚他是什么.作为一个前端开发人员,JavaScript应该算作是最核心之一的 ...

  8. 深入理解JavaScript系列

    转自http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html 深入理解JavaScript系列(1):编写高质量JavaScript代码 ...

  9. [JS]深入理解JavaScript系列(4):立即调用的函数表达式

    转自:汤姆大叔的博客 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行.在详细了解这个之前,我们来谈了解一下"自执行"这个叫法 ...

随机推荐

  1. Oracle得知(十五):分布式数据库

    --分布式数据库的独立性:分布数据的独立性指用户不必关心数据怎样切割和存储,仅仅需关心他须要什么数据. --本地操作 SQL> sqlplus scott/tiger --远程操作 SQL> ...

  2. asp.net模板控件示例

    原文:asp.net模板控件示例 模板控件允许将控件数据与其表示形式相分离,模板化控件不提供用户界面. 编写它则是为了实现一个命名容器以及包含属性和方法可由宿主页访问的类,MSDN是这样解释的. 下面 ...

  3. 【Android基础】单元测试的配置

    1.在AndroidManifest清单文件中进行配置 <application android:allowBackup="true" android:debuggable= ...

  4. spring常规任务(轻便易)

    spring提供了定时任务功能.我们不需要第三者jar包支持.spring够了. 代码: package com.inth.product.web.task; import java.util.Dat ...

  5. POJ3467(预处理)

    Cross Counting Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 1331   Accepted: 375 De ...

  6. jqm的多列布局demo,html5的多列布局demo,多列布局的具体解说,html5开发实例具体解释

    因为移动设备屏幕宽度较小,所以一般不建议使用多列布局.但有时你可能须要并排放置一些元素(如button之类的). jQuery Mobile通过约定的类名ui-grid来提供了一种基于css的多列布局 ...

  7. Hadoop 2.6.0分布式部署參考手冊

    Hadoop 2.6.0分布式部署參考手冊 关于本參考手冊的word文档.能够到例如以下地址下载:http://download.csdn.net/detail/u012875880/8291493 ...

  8. Androids含文档erver结束(工具包 Httputils)两

    在同server在...的基础上,本文client还登录界面 Andriod简单http get请求基础上,用户注冊后跳转到下载界面,本文下载界面仅仅有两个View,一个是textView显示注冊后u ...

  9. POSIX 螺纹具体解释(1-概要)

    线程是有趣的 线程类似于进程.如同进程,线程由内核按时间分片进行管理.在单处理器系统中,内核使用时间分片来模拟线程的并发运行.这样的方式和进程的同样. 而在多处理器系统中,如同多个进程.线程实际上一样 ...

  10. 本人第一个android游戏《新连连看》上架

    经过艰苦奋战了几天,本人的第一个android游戏<新连连看>最终完毕了第一个版本号,比較简陋.另一部分功能保留没有开放.等第二个版本号再上.用的libgdx框架.可能不是非常出名,可是本 ...