小白初读冴羽大神Blog的笔记

2019-03-20  本文已影响0人  派大星的博客

给自己看的,就是个蓝图,没价值!

➡️➡️➡️冴羽大神Blog


通过阅读ECMAScript标准,你可以学会怎样实现一个脚本语言;

而通过阅读JavaScript文档,你可以学会怎样使用脚本语言编程。


词法作用域(lexical scoping),也就是静态作用域

local scope: 局部作用域


可执行代码(executable code)


执行上下文(execution context)

执行上下文栈(Execution context stack,ECS)

全局执行上下文,我们用 globalContext

函数执行上下文 functionContext


对于每个执行上下文,都有三个重要属性:


在函数上下文中,我们用活动对象(activation object, AO)来表示变量对象。

变量对象会包括:

  1. 函数的所有形参 (如果是函数上下文)
  1. 函数声明
  1. 变量声明

function foo(a) {

 var b = 2;

 function c() {}

 var d = function() {};

 b = 3;

}

foo(1);

初始化:

AO = {

 arguments: {

 0: 1,

 length: 1

 },

 a: 1,

 b: undefined,

 c: reference to function c(){},

 d: undefined

}

执行后:


AO = {

 arguments: {

 0: 1,

 length: 1

 },

 a: 1,

 b: 3,

 c: reference to function c(){},

 d: reference to FunctionExpression "d"

}

  1. 全局上下文的变量对象初始化是全局对象
  2. 函数上下文的变量对象初始化只包括 Arguments 对象
  3. 在进入执行上下文时会给变量对象添加形参、函数声明、变量声明等初始的属性值
  4. 在代码执行阶段,会再次修改变量对象的属性值

?? 函数的作用域在函数定义的时候就决定了。

这是因为函数有一个内部属性 [[scope]],当函数创建的时候,就会保存所有父变量对象到其中,你可以理解 [[scope]] 就是所有父变量对象的层级链,但是注意:[[scope]] 并不代表完整的作用域链!


关注大神的github: JavaScript深入之从ECMAScript规范解读this


规范:Annotated ECMAScript 5.1

ECMAScript 的类型分为语言类型和规范类型。

ECMAScript 语言类型是开发者直接使用 ECMAScript 可以操作的。其实就是我们常说的Undefined, Null, Boolean, String, Number, 和 Object。

而规范类型相当于 meta-values,是用来用算法描述 ECMAScript 语言结构和 ECMAScript 语言类型的。规范类型包括:Reference, List, Completion, Property Descriptor, Property Identifier, Lexical Environment, 和 Environment Record。


Reference

这段讲述了 Reference 的构成,由三个组成部分,分别是:


base value 就是属性所在的对象或者就是 EnvironmentRecord,它的值只可能是 undefined, an Object, a Boolean, a String, a Number, or an environment record 其中的一种。

referenced name 就是属性的名称。


var foo = {

 bar: function () {

 return this;

 }

};

foo.bar(); // foo

// bar对应的Reference是:

var BarReference = {

 base: foo,

 propertyName: 'bar',

 strict: false

};

1.计算 MemberExpression 的结果赋值给 ref(括号之前部分)

2.判断 ref 是不是一个 Reference 类型

2.1 如果 ref 是 Reference,并且 IsPropertyReference(ref) 是 true, 那么 this 的值为 GetBase(ref)

2.2 如果 ref 是 Reference,并且 base value 值是 Environment Record, 那么this的值为 ImplicitThisValue(ref)

2.3 如果 ref 不是 Reference,那么 this 的值为 undefined


变量提升 var

块级作用域存在于:

块级声明用于声明在指定块的作用域之外无法访问的变量。

let 和 const 都是块级声明的一种。

1.不会被提升

2.重复声明报错

3.不绑定全局作用域

const 用于声明常量,其值一旦被设定不能再被修改,否则会报错。

值得一提的是:const 声明不允许修改绑定,但允许修改值。这意味着当用 const 声明对象时:

const data = {

 value: 1

}

// 没有问题

data.value = 2;

data.num = 3;

// 报错

data = {}; // Uncaught TypeError: Assignment to constant variable.

临时死区(Temporal Dead Zone)

因为 JavaScript 引擎在扫描代码发现变量声明时,要么将它们提升到作用域顶部(遇到 var 声明),要么将声明放在 TDZ 中(遇到 let 和 const 声明)。访问 TDZ 中的变量会触发运行时错误。只有执行过变量声明语句后,变量才会从 TDZ 中移出,然后方可访问。


箭头函数 arrow function

An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.

箭头函数表达式的语法比函数表达式更简洁,并且没有自己的thisargumentssupernew.target。这些函数表达式更适用于那些本来需要匿名函数的地方,并且它们不能用作构造函数。

引入箭头函数有两个方面的作用:更简短的函数并且不绑定this。

箭头函数的特性一:

总结

最后,关于箭头函数,引用 MDN 的介绍就是:

An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.

翻译过来就是:

箭头函数表达式的语法比函数表达式更短,并且不绑定自己的this,arguments,super或 new.target。这些函数表达式最适合用于非方法函数(non-method functions),并且它们不能用作构造函数。

?? 那么什么是 non-method functions 呢?

我们先来看看 method 的定义:

A method is a function which is a property of an object.

对象属性中的函数就被称之为 method,那么 non-mehtod 就是指不被用作对象属性中的函数了,可是为什么说箭头函数更适合 non-method 呢?

让我们来看一个例子就明白了:

var obj = {
  i: 10,
  b: () => console.log(this.i, this),
  c: function() {
    console.log( this.i, this)
  }
}
obj.b();
// undefined Window
obj.c();
// 10, Object {...}
上一篇 下一篇

猜你喜欢

热点阅读