二.[前端总结]之JavaScript篇

 

 

1.原型 / 构造函数 / 实例

 

原型( prototype ): ⼀个简单的对象,⽤于实现对象的 属性继承。可以简单的理解成对象的爹。 Firefox Chrome 中,每 JavaScript 对象中都包含⼀个 proto (⾮标准)的属性指向它爹(该对象的原型),  obj. proto 进⾏访问。

构造函数: 可以通过 new 来 新建⼀个对象 的函数。

实例: 通过构造函数和  new 创建出来的对象,便是实例。 实例通过   proto 指向原型,通过 constructor 指向构造函数。

 

Object 为例,我们常⽤的 Object 便是⼀个构造函数,因此我们可以通过它构建实例。

// 

const instance = new Object()

 

则此时 实例为 instance , 构造函数为 Object ,我们知道,构造函数拥有⼀个 prototype 的属性指向原型,因此原型为:

// 

const prototype = Object.prototype

 

这⾥我们可以来看出三者的关系:

实例. proto === 

原型.constructor === 构造函数构造函数.prototype === 原型

 

 

// 这条线其实是是基于原型进⾏获取的,可以理解成⼀条基于原型的映射线

// 例如:

// const o = new Object()

// o.constructor === Object    --> true

// o. proto = null;

// o.constructor === Object    --> false

实例.constructor === 构造函数

 

 

2.原型链:

原型链是由原型对象组成,每个对象都有  proto 属性,指向了创建该对象的构造函数的原型    proto 将对象连接起来组成了原型链。是⼀个⽤来实现继承和共享属性的有限的对象链。

 

属性查找机制: 当查找对象的属性时,如果实例对象⾃身不存在该属性,则沿着原型链往上⼀级查找,找到时则输出,不存在时,则继续沿着原型链往上⼀级查找,直⾄最顶级的原  型对象 Object.prototype ,如还是没找到,则输 undefined ;

属性修改机制:  只会修改实例对象本身的属性,如果不存在,则进⾏添加该属性,如果需要修改原型的属性时,则可以⽤: b.prototype.x = 2 ;但是这样会造成所有继承于该对象的实例的属性发⽣改变。

 

 

3.执⾏上下⽂(EC)

 

执⾏上下⽂可以简单理解为⼀个对象:

 

它包含三个部分:

 变量对象( VO )

作⽤域链(词法作⽤域)

this 

 

它的类型:

全局执⾏上下

函数执⾏上下⽂

eval 执⾏上下⽂

 

代码执⾏过程:

 

创建 全局上下 ( global EC )

全局执⾏上下 ( caller ) 逐 上⽽ 执⾏。遇到函数时,函数执⾏上下⽂( callee ) push 到执⾏栈顶层

函数执⾏上下⽂被激活,成为    active EC , 开始执⾏函数中的代码  caller 被挂起函数

执⾏完后 callee  pop 移除出执⾏栈,控制权交还全局上下 ( caller ),继续执⾏

 

4.变量对象

 

变量对象,是执⾏上下⽂中的⼀部分,可以抽象为⼀   数据作⽤域,其实也可以理解为就是⼀个简单的对象,它存储着该执⾏上下⽂中的所 变量和函数声明(不包含函数表达

式)。

动对象 ( AO ): 当变量对象所处的上下⽂为 active EC 时,称为活动对象。

 

5. 作⽤域

 

执⾏上下⽂中还包含作⽤域链。理解作⽤域之前,先介绍下作⽤域。作⽤域其 实可理解为该上下⽂中声明 变量和声明的作⽤范围。可分为级作⽤域 函数作⽤域

 

特性:

 

声明提前: ⼀个声明在函数体内都是可⻅的, 函数优先于变量

⾮匿名⾃执⾏函数,函数变量为 只读 状态,⽆法修改

js

let foo = function() { console.log(1) }

(function foo() {

foo = 10 // 由于foo在函数中只为可读,因此赋值⽆效

console.log(foo)

}())

 

// 结果打印: ƒ foo() { foo = 10 ; console.log(foo) }

 

6. 作⽤域链

 

我们知道,我们可以在执⾏上下⽂中访问到⽗级甚⾄全局的变量,这便是作⽤  域链的功劳。作⽤域链可以理解为⼀组对象列表,包含 ⽗级和⾃身的变量对象,因此我们便能通过作⽤域链访问到⽗级⾥声明的变量或者函数。

 

由两部分组成:

 

[[scope]] 属性: 指向⽗级变量对象和作⽤域链,也就是包含了⽗级的 [[scope]] AO AO : ⾃身活动对象

 

如此 [[scopr]] 包含 [[scope]] ,便⾃上⽽下形成⼀ 链式作⽤域。

 

 

7. 闭包

 

闭包属于⼀种特殊的作⽤域,称为  静态作⽤域。它的定义可以理解为: ⽗函数被销毁 的情况下,返回出的⼦函数的 [[scope]] 中仍然保留着⽗级的单变量对象和作⽤域链,因此可以继续访问到⽗级的变量对象,这样的函数称为闭

 

 

闭包会产⽣⼀个很经典的问题:

 

多个⼦函数的 [[scope]] 都是同时指向⽗级,是完全共享的。因此当⽗级的变量对象被修改时,所有⼦函数都受到影响。

 

••解决:**

 

变量可以通过 函数参数的形式 传⼊,避免使⽤默认的 [[scope]] 向上查

使⽤ setTimeout 包裹,通过第三个参数传⼊

使⽤ 块级作⽤域,让变量成为⾃⼰上下⽂的属性,避免共享

 

8.script 引⼊⽅式:

 

html