你不知道的javascript(一)
1、js的编译原理
首先,js是一门编译型语言(动态、解释执行),可以简单理解为,运行时才编译,当然速度很快。
作为语言,编译时会经历几个阶段:
1、分词/词法分析
2、解析/语法分析
3、代码生成
var a = 2
对于一个 var a = 2
编译阶段所做的事情就是
1、将 var a = 2 分解成一些词法单元 var、a、=、2
2、将上述转化为AST(抽象语法树)
3、将 AST 转化为代码执行(分配内存 ,创建变量a ,储存a值)
2、编译过程中该怎么做?做些什么?------作用域
上面我们知道了,代码会经历三个阶段,那这三个阶段应该怎么做呢?或者说需要怎么去配合,这就引出了 作用域的概念-----其实就是变量查找的规则
在编译过程中需要 三个兄弟共同完成
1、引擎-------负责整个编译和执行过程
2、编译器------负责词法分析、代码生成
3、作用域------收集和维护变量标识符,制定查找规则(其实内含了变量提升)
3、结合编译过程,理解作用域
三个编译过程的协调合作,实现了代码生成,在过程中,引入两个概念,LHS(左查询)、RHS(右查询)
在对 var a = 2 引擎进行编译时,先进行 左查询,查找变量a ------>作用域
然后进行赋值操作 a = 2
LHS----变量赋值
RHS----得到xxx的值
在对代码进行编译时,词法分析中会进行 LHS和RHS,进而查找变量、变量的赋值
变量的查找就先在当前的词法作用域中找,如果没有就继续往上,一直到达建筑顶层
这就是作用域链(继续深入就会发现一些伪装的作用域)
对于 b = 2
这是赋值操作,会进行 LHS,和 RHS不同,当这个变量b 不存在时,会自动创建一个,这就是 js中,未声明变量,结果会变成全局变量的原因(非严格模式下)
对于 console.log(c)
属于获取 c 的值 ,进行 RHS,然而作用域中找不到变量c的值,所以报错ReferenceError
4、欺骗词法作用域
eval、with,用的少,作为了解吧,我的印象中好像看见过with
var obj = {
a: 1,
b: 2,
c: 3
};
with (obj) {
a = 3;
b = 4;
c = 5;
}
人话就是 让你 取对象的值时,少.XXX,with实际是引入了一个新的词法作用域
5、词法作用域
js 的作用域是 词法作用域 非动态作用域
function foo() {
var a = 2
bar()
}
function bar(){
console.log(a)
}
var a = 3
foo() // 3
动态作用域,在运行时创建的作用域,有点类似this
如果说,js是动态作用域,那么 输出 a 应该等于 2,因为作bar()处在嵌套的函数内调用的,但是 js是词法作用域,在写代码或者定义的时候就确定了
6、关于this
6.1 this的出现,是为了,反复传递context对象而出现
6.2 this的绑定出现在运行时,而不是编写代码时
6.3 四条规则,判断this的绑定对象
1、new调用?绑定到新对象
2、call、apply、bind、?绑定到指定对象
3、上下文对象中调用?(obj.fn())绑定到上下文对象
4、默认 全局 window
es6中,箭头函数并不遵循这四条规则,会继承外层函数的this
本文地址:https://blog.csdn.net/qq_45219069/article/details/109239003
上一篇: JSP实现百万富翁猜数字游戏