前端基础 | 理解原型-作用域-执行上下文
用自己的话记录下最近学到的几个知识点:理解原型-作用域-执行上下文
用自己的话记录下最近学到的几个知识点
一、原型与原型链
基础代码:
1 | // 使用构造函数创建一个对象 |
prototype
每个函数都有一个 prototype
属性。
prototype
是函数才会有的属性。
函数的 prototype
属性是指通过调用构造函数而创建的对象实例的原型
,即上面代码中person
的原型。
proto
每一个JavaScript
对象(除了 null
)都具有的一个属性,叫__proto__
,这个属性会指向该对象的原型。
1 | function Person() {} |
⚠️注意:__proto__
存在于 实例与构造函数的原型之间,而不是存在于实例与构造函数之间
可通过Object.getPrototypeOf()
获取对象的原型
1 | Object.getPrototypeOf(person) === Person.prototype // true |
constructor
constructor
是原型的一个属性,指向该原型所对应的构造函数,所有对象都会自动获得这个属性
1 | Person.prototype.constructor === Person // true |
读取实例的属性时,如果在实例中找不到,就会去找原型上的该属性,如果还找不到,会继续去原型的原型上查找,直到找到最顶层为止.
原型链
由相互关联的原型组成的链状结构就是原型链,即通过 __proto__ 把原型连起来的链状结构
例子:
1 | function Person() {} |
Object.prototype
是最顶层原型,它的原型是 null
,即
1 | Obkect.prototype.__proto__ === null |
图中红线所组成的连接就叫原型链
二、词法作用域和动态作用域
JavaScript
采用的是词法作用域
,或者叫静态作用域
因为 js是采用的词法作用域
,所以函数的作用域在函数定义的时候就决定了
。
但在动态作用域
中,函数的作用域在函数调用的时候决定
。
1 | var value = 1; |
上述代码:
- 如果 js 是动态作用域,则执行
bar()
后,应输出 2
; - 如果 js 是词法作用域,则执行
bar()
后,应输出 1
;
在浏览器中执行上面代码可以知道输出结果为 1
。验证了 js 是词法作用域。
再看两个例子:
1 | var scope = "global scope"; |
1 | var scope = "global scope"; |
输出结果都为:local scope
三、执行上下文
执行上下文
就是当前 JavaScript 代码被解析和执行时所在环境
的抽象概念
, JavaScript 中运行任何的代码都是在执行上下文中运行。
总共有三种类型:
- 全局执行上下文: 只有一个,浏览器中的全局对象就是
window
对象,this
指向这个全局对象。 - 函数执行上下文: 存在无数个,只有在函数被调用的时候才会被创建,每次调用函数都会创建一个新的执行上下文。
- Eval 函数执行上下文: 指的是运行在
eval
函数中的代码,很少用而且不建议使用。
执行栈
,也被叫做调用栈,具有 LIFO(后进先出)结构
。
当 JavaScript
引擎首次读取你的脚本时,它会创建一个全局执行上下文
并将其推入当前的执行栈。
执行栈的底部始终有个全局执行上下文。
每发生一个函数调用就会创建一个执行上下文,并推进执行栈中,执行完后,从栈顶删除。
例子:
1 | let a = 'Hello World!'; |
js执行过程,可以看看我之前总结的这一篇文章:
http://www.brandhuang.com/article/1576067877012
执行上下文相关推荐文章:
先就记录这几个知识点吧,多了一次性也记不住,大概率你也不会来看第二遍