Fork me on GitHub

《你不知道的Javascript》书中有趣的知识点一

最近在看《你不知道的Javascript》,里面有不少有趣的知识点,在这里做一个分享

一、LHS查询与RHS查询

1、当变量出现在赋值操作的左侧时进行LHS查询,出现在右侧时进行RHS查询。

讲得更准确一点,RHS查询与简单地查找某个变量的值别无二致,而LHS查询则是试图找到变量的容器本身,从而可以对其赋值。从这个角度说,RHS并不是真正意义上的“赋值操作的右侧”,更准确地说是“非左侧”。

2、例如:

1
console.log( a );

其中对 a 的引用是一个RHS引用,因为这里 a 并没有赋予任何值。相应地,需要查找并取得 a 的值,这样才能将值传递给console.log(..)

3、再例如:

1
a = 2;

这里对 a 的引用则是LHS引用,因为实际上我们并不关心当前的值是什么,只是想要为 = 2 这个赋值操作找到一个目标。

4、LHS和RHS的含义是“赋值操作的左侧或右侧”并不一定意味着就是“=赋值操作符的左侧或右侧”。赋值操作还有其他几种形式,因此在概念上最好将其理解为“赋值操作的目标是谁(LHS)”以及“谁是赋值操作的源头(RHS)”

5、小测试,试试以下代码有几处LHS查询以及RHS查询:

1
2
3
4
5
function foo(a) {   
var b = a;
return a + b;
}
var c = foo( 2 );

答案是有3处LHS查询以及以及有4处RHS查询。

二、块作用域

1、参考for循环的例子:

1
2
3
4
5
for (var i=0; i<10; i++) {
console.log( i );
}

console.log( i ); //10

这时候在for循环内部使用(至少是应该只在内部使用)的变量i污染到整个函数作用域中了。

2、使用 let 可以避免这种情况:

1
2
3
4
for (let i=0; i<10; i++) {
console.log( i );
}
console.log( i ); // ReferenceError

三、函数声明提升

1、参考如下代码:

1
2
3
4
foo(); // hello
function foo() {
console.log("hello")
};

由于变量提升,以上函数能够正常运行。

2、再参考如下代码:

1
2
3
4
foo(); // 不是ReferenceError, 而是TypeError! 
var foo = function bar() {
console.log("hello")
};

由于变量提升,foo在刚开始运行代码时便被申明,因此 foo() 不会导致 ReferenceError 。但是 foo 此时并没有赋值,因此抛出TypeError异常。

3、再参考如下代码:

1
2
3
4
5
foo(); // TypeError 
bar(); // ReferenceError
var foo = function bar() {
console.log("hello")
};

这里 bar()ReferenceError 错是因为函数表达式不会被提升,即使是具名的函数表达式也是如此。

4、另外,一个普通块内部的函数声明通常会被提升到所在作用域的顶部,这个过程不会像下面的代码暗示的那样可以被条件判断所控制:

1
2
3
4
5
6
7
foo(); // "b" 
var a = true;
if (a) {
function foo() { console.log("a"); }
} else {
function foo() { console.log("b"); }
}

四、参考资料

github’You-Dont-Know-JS’

你不知道的Javascript(上)(中文版) 密码:x7ge

-------------本文结束感谢您的阅读-------------