美文网首页
前端指南-JavaScript

前端指南-JavaScript

作者: MrZac_ | 来源:发表于2019-05-19 20:28 被阅读0次

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

    原型(prototype): 一个简单的对象,用于实现对象的 属性继承。可以简单的理解成对象的爹。在 Firefox 和 Chrome 中,每个JavaScript对象中都包含一个__proto__ (非标准)的属性指向它爹(该对象的原型),可obj.__proto__进行访问。

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

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

    说了一大堆,大家可能有点懵逼,这里来举个栗子,以Object为例,我们常用的Object便是一个构造函数,因此我们可以通过它构建实例。

    // 实例

    constinstance =newObject();

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

    // 原型

    constprototype =Object.prototype;

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

    实例.__proto__ === 原型;

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

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

    原型.constructorr === 构造函数;

    放大来看,我画了张图供大家彻底理解:

    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),继续执行

    2.变量对象

    变量对象,是执行上下文中的一部分,可以抽象为一种 数据作用域,其实也可以理解为就是一个简单的对象,它存储着该执行上下文中的所有 变量和函数声明(不包含函数表达式)

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

    3. 作用域

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

    特性:

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

    非匿名自执行函数,函数变量为 只读 状态,无法修改

    constfoo =1(

    (functionfoo(){

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

    console.log(foo);

    })()

    );

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

    4.作用域链

    我们知道,我们可以在执行上下文中访问到父级甚至全局的变量,这便是作用域链的功劳。作用域链可以理解为一组对象列表,包含 父级和自身的变量对象,因此我们便能通过作用域链访问到父级里声明的变量或者函数。

    由两部分组成: - [[scope]]属性: 指向父级变量对象和作用域链,也就是包含了父级的[[scope]]和AO - AO: 自身活动对象

    如此 [[scopr]]包含[[scope]],便自上而下形成一条 链式作用域

    5. 闭包

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

    闭包会产生一个很经典的问题: - 多个子函数的[[scope]]都是同时指向父级,是完全共享的。因此当父级的变量对象被修改时,所有子函数都受到影响。

    解决: - 变量可以通过 函数参数的形式 传入,避免使用默认的[[scope]]向上查找 - 使用setTimeout包裹,通过第三个参数传入 - 使用 块级作用域,让变量成为自己上下文的属性,避免共享

    6. script 引入方式:

    html 静态script引入

    js 动态插入script

    script defer: 异步加载,元素解析完成后执行

    script async: 异步加载,与元素渲染并行执行

    7. 对象的拷贝

    浅拷贝: 以赋值的形式拷贝引用对象,仍指向同一个地址,修改时原对象也会受到影响- Object.assign - 展开运算符(…)

    深拷贝: 完全拷贝一个新对象,修改时原对象不再受到任何影响 - JSON.parse(JSON.stringify(obj)): 性能最快 - 具有循环引用的对象时,报错 - 当值为函数或undefined时,无法拷贝

    递归进行逐一赋值

    相关文章

      网友评论

          本文标题:前端指南-JavaScript

          本文链接:https://www.haomeiwen.com/subject/zqzqzqtx.html