javascript核心

一、Object

An object is a collection of properties and has a single prototype object. The prototype may be either an object or the null value.

Object是有属性集合以及单例的原型对象组成的。原型可以为object和null。

Object的原型对象是通过对象内部的[[Prototype]]属性来引用的。下图我们将用__<internal-property>__ 替代[[Prototype]] (在FF的JS引擎中使用的是__proto__).

var foo = {
  x: 10,
  y: 20
};

上面的代码段,我们将有2个显示属性和一个隐式__proto__ 属性,该隐式属性是foo原型的引用。

这些属性有什么用,下面就来看看原型链。

二、A prototype chain

原型对象也是简单的对象也可以有他自己的原型,如果一个原型有不为null的引用指向到他的原型(If a prototype has a non-null reference to its prototype),如此反复,我们就成为原型链。原型链是有限的对象链(能有终点的),用来继承和共享属性。

下面我们就来使用基于原型链的继承写几个类。

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
};
 
// call the inherited method
b.calculate(30); // 60
c.calculate(40); // 80

对象b和c都能使用a的方法,这就是原型链起的作用。

规则很简单:如果一个方法或者属性在当前对象找不到,他会尝试着去原型链中查找,如果原型中没找到,则会从原型的原型中查找,直到整个原型链。最先找到的那个属性和方法将会被使用,如果遍历了整个原型链都未找到则会返回undefined。

注意,this的取值(that this value in using an inherited method is set to the original object, but not to the (prototype) object in which the method is found.)也是从原型链中取得的,比如this.y 是b和c中的值而不是a,但是this.x却是从a中取得的。

如果一个原型没有直接指明一个object,那么将使用Object.prototype.作为__proto__,而对象Object.prototype 自己的__proto__最终会指向null。

下图清晰的描绘了原型链

在FF中运行的结果:

通常我们创建对象的时候希望他会有相同的状态和属性值,这时我们就需要利用构造函数(constructor function 

三、constructor

构造函数除了能够创建一个特定模式的对象之外,还有另一个用途:为新建的对象自动设置一个原型对象,这个原型对象存储在ConstructorFunction.prototype 属性中。例如:我们利用构造函数重写之前的代码

// a constructor function
function Foo(y) {
  // which may create objects
  // by specified pattern: they have after
  // creation own "y" property
  this.y = y;
}
 
// also "Foo.prototype" stores reference
// to the prototype of newly created objects,
// so we may use it to define shared/inherited
// properties or methods, so the same as in
// previous example we have:
 
// inherited property "x"
Foo.prototype.x = 10;
 
// and inherited method "calculate"
Foo.prototype.calculate = function (z) {
  return this.x + this.y + z;
};
 
// now create our "b" and "c"
// objects using "pattern" Foo
var b = new Foo(20);
var c = new Foo(30);
 
// call the inherited method
b.calculate(30); // 60
c.calculate(40); // 80
 
// let's show that we reference
// properties we expect
 
console.log(
 
  b.__proto__ === Foo.prototype, // true
  c.__proto__ === Foo.prototype, // true
 
  // also "Foo.prototype" automatically creates
  // a special property "constructor", which is a
  // reference to the constructor function itself;
  // instances "b" and "c" may found it via
  // delegation and use to check their constructor
 
  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
 
);

四、execution context stack

ECMAScript代码分为三种:全局代码、函数代码、eval代码。每个代码都会在执行上下文中运行。全局上下文只有一个,而函数和eval执行上下文却有很多实例。每调用一次函数都会进入函数执行上下文,每次调用eval函数,都会进入eval执行上下文执行代码。由于每次调用函数都会产生一个新的执行状态的上下文,所以每个函数都可能产生无限个上下文。一个执行上下文会激活另一个上下文,比如一个函数调用另一个函数,最终会产生一个执行上下文堆栈。一个上下文激活另一个上下文则被称为caller,被激活的则称为callee。一个callee可能同时又是caller(比如一个函数被全局函数调用之后,可能会调用内部函数)。

当调用者(caller)激活(calls)被调用者(callee),会中断当前的执行,同时将控制流转向被调用者。被调用者压入栈成为正在执行的执行上下文,待到调用结束,将控制转交给调用者,继续执行调用者的部分直到结束。被调用者如果由于未捕捉的异常直接返回或者退出,则会终止一个或多个上下文。

执行上下文堆栈由program runtime负责,栈的最顶端即是active context。

当程序进入全局执行上下文(global execution context),即stack中最低端的的第一个那个元素。首先全局代码提供初始化,创建必须的对象和函数。在执行全局上下文的时候会激活一些已经创建好的函数,进入函数的执行上下文,同时将一些新的元素压入堆栈。等到初始化结束的时候,系统会进入等待阶段,等待一些事件,比如用户鼠标单击事件,以便激活新的函数,进入新的执行上下文。

堆栈中的每一个执行上下文都可以被描述成一个对象。接下来,我们看看这个对象的结构,以及执行它的代码的时候都需要哪些具体的属性。

五、Execution context

每一个执行上下文对象都有一个属性集合,我们称之为上下文状态(context’s state),这些属性集合用来跟踪执行进度以及关联到相关执行代码。结构图如下:

除了(a variable object, a this value and a scope chain)这三个属性之外,在具体的过程中执行上下文还需要其他一些附加的属性。

接下来详细讨论下这三个属性。


 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值