每周笔记

原创 青春正当时 随笔 JavaScript 66阅读 2019-02-22 17:24:18 举报

作用域和作用域链

一、什么是作用域?

作用域是你的代码在运行时,各个变量、函数和对象的可访问性。(可产生作用的区域)

二、JavaScript中的作用域

在 JavaScript 中有两种作用域

  • 全局作用域
  • 局部作用域

当变量定义在一个函数中时,变量就在局部作用域中,而定义在函数之外的变量则从属于全局作用域。每个函数在调用的时候会创建一个新的作用域。

1.全局作用域

当你在文档中(document)编写 JavaScript 时,你就已经在全局作用域中了。JavaScript
文档中(document)只有一个全局作用域。定义在函数之外的变量会被保存在全局作用域中

全局作用域里的变量能够在其他作用域中被访问和修改

2.局部作用域

定义在函数中的变量就在局部作用域中。并且函数在每次调用时都有一个不同的作用域。这意味着同名变量可以用在不同的函数中。因为这些变量绑定在不同的函数中,拥有不同作用域,彼此之间不能访问。

3.块语句(JS没有块级作用域)

块级声明包括if和switch,以及for和while循环,和函数不同,它们不会创建新的作用域。在块级声明中定义的变量从属于该块所在的作用域。也就是说在for、if、while等语句内部的声明的变量与在外部声明是一样的,在这些语句外部也可以访问和修改这些变量的值。

ECMAScript 6 引入了let和const关键字。这些关键字可以代替var

和var关键字不同,let和const关键字支持在块级声明中创建使用局部作用域(块级作用域)

一个应用中全局作用域的生存周期与该应用相同。局部作用域只在该函数调用执行期间存在

4.词法作用域

所谓的 词法( 代码 )作用域, 就是代码在编写过程中体现出来的作用范围. 代码一旦写好, 不用执行, 作用范围就已经确定好了.
这个就是所谓词法作用域.这意味着函数运行在定义它的作用域中,而不是在调用它的作用域中

在 js 中词法作用域规则:

  • 函数允许访问函数外的数据.
  • 整个代码结构中只有函数可以限定作用域.
  • 作用规则首先使用提升规则分析
  • 如果当前作用规则中有名字了, 就不考虑外面的名字

词法作用域

var用来将变量定义在词法作用域中(也就是function中)

a就被函数someFunc框在了词法作用域中

块级作用域

letconst用来将变量定义在块级作用域中(也就是花括号中)

b就被if的花括号框在了块级作用域中

5.作用域链

可以发现只有函数可以制造作用域结构. 那么只要是代码, 至少有一个作用域, 即全局作用域. 凡是代码中有函数,那么这个函数就构成另一个作用域. 如果函数中还有函数, 那么再这个作用域中就 又可以诞生一个作用域. 那么将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构.

作用域嵌套

作用域是可以嵌套的,任务一中提到的词法作用域和块级作用域都可以嵌套其他作用域
(块级作用域仅对ES6而言)

inner就是嵌套在someFunc(词法作用域)中的词法作用域

while就是嵌套在if(块级作用域)中的块级作用域

if就是嵌套在someFunc(词法作用域)中的块级作用域

作用域中的变量访问

所有的嵌套作用域都遵循以下规则:
内部作用域有权访问外部作用域,反之不成立。

栗子:

function someFunc(){

}
inner有权访问innerVarouterVar,但是someFunc只能访问到outerVar

多重嵌套作用域

作用域是可以任意嵌套的,但是都要遵循上面的规则。
再附加一个规则:
兄弟作用域不可相互访问

栗子:

innerinner2都是someFunc中的作用域,正如someFunc不能访问inner们的作用域一样,inner们之间也不能相互访问。

作用域树

从上向下看这个嵌套作用域,就是棵树!
看代码:

看树:

要记住的是:inner作用域可以访问外部作用域,但是反之不成立; foo()可以访问inner2()中的变量,inner2()可以访问someFunc()中的变量,这棵树倒过来似乎更有意义,就成了链!!

作用域链

从最里面看到最外面就构成了作用域链

简述一下Vue.js的template编译过程?

先上一张图大致看一下整个流程

从上图中我们可以看到compile是从mount后开始进行中, 整体逻辑分为三个部分

  • 解析器(parse) - 将 模板字符串 转换成 element ASTs
  • 优化器(optimize) - 对 AST 进行静态节点标记,主要用来做虚拟DOM的渲染优化
  • 代码生成器(generate) - 使用 element ASTs 生成 render 函数代码字符串
开始前先解释一下AST

AST(abstract syntax tree 抽象语法树), 是源代码的抽象语法结构的树状表现形式

从代码上简单理解一下

AST会经过generate得到render函数,render的返回值是VNode, VNode的源码可以见https://github.com/vuejs/vue/blob/8a2dbf50105ea729125a42fecfe2c2f0371d7836/src/core/vdom/vnode.js

解析器(parse)

源码地址https://github.com/vuejs/vue/blob/8a2dbf50105ea729125a42fecfe2c2f0371d7836/src/compiler/parser/index.js

parse 的目标是把 template 模板字符串转换成 AST 树,它是一种用 JavaScript 对象的形式来描述整个模板。那么整个 parse 的过程是利用正则表达式顺序解析模板,当解析到开始标签、闭合标签、文本的时候都会分别执行对应的回调函数,来达到构造 AST 树的目的

优化器(optimize)

源码地址https://github.com/vuejs/vue/blob/8a2dbf50105ea729125a42fecfe2c2f0371d7836/src/compiler/optimizer.js

通过 optimize 把整个 AST 树中的每一个 AST 元素节点标记了 static 和 staticRoot, optimize 的过程,就是深度遍历这个 AST 树,去检测它的每一颗子树是不是静态节点,如果是静态节点则它们生成 DOM 永远不需要改变

代码生成器(generate)

源码地址https://github.com/vuejs/vue/blob/8a2dbf50105ea729125a42fecfe2c2f0371d7836/src/compiler/codegen/index.js

把优化后的 AST 树转换成可执行的代码

总结

首先通过parse将template解析成AST,其次optimize对解析出来的AST进行标记,最后generate将优化后的AST转换成可执行的代码

如何让文本只显示两行——块级文字省略

在页面显示中我们经常会需要进行省略,比如简介里面的省略,比如固定div中字数超过限制之后的省略。我们可以用css轻松做到。

单行文字的省略

单行文字省略比较简单。关键代码如下:

最终的效果是:

当一行中的文本不固定的时候,可以设置一个max-width,当超过这个最大宽度,就进行省略,其他的时候不省略。常见应用如:历史搜索记录里面的记录显示。

多行文字的省略

多行文字的省略可以用css来做,也可以用js来做。先来看看css的做法。

css:

多行文字的省略主要用到-webkit-line-clamp属性,主要用来限制在一个块元素显示的文本的行数。但是这个属性不规范,要实现该效果,必须结合其他外来的WebKit属性。

来看具体实现:

最终显示的效果如下:

这个省略的效果也可以用js来做:

js:

js的做法适用于最多适配多少个字符的情况,但是如果想控制显示几行的话,css的方式显然更加方便。

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复