​《你不知道的Javascript-中册》阅读笔记

第一部分

第一章

1、

var a;

a; // undefined

b; // ReferenceError: b is not defined

undefined 和 is not defined 是两回事

2.

// 这样会抛出错误

if(DEBUG) {

    console.log( "Debugger is starting" )

}

//这样是安全的

if (typeof DEBUG !== "undefined") {

    console.log( "Debugging is starting" )

}

第二章

1.

var b = 42.;  //42.这样的写法没问题,只是不常见,但从代码的可读性考虑,不建议这样写。

42.toFixed(3) 是无效语法,因为 . 被视为常量42.的一部分 , 42..toFixed(3) 则没问题

2.

Object.is() 主要是用来处理那些特殊的相等比较 

Object.is(NaN, NaN) //true

Object.is(0, -0) //true

3.

对包含循环引用的对象执行JSON.stringify(..) 会出错

第4章

1.

以下这些是假值:

undefined

null

false

+0, -0 和NaN

""

假值的布尔强制类型转换结果为false

理论上 假值列表以外的都应该是真值。  

2.

使用 Date.now() 来获取当前时间戳,比new Date().getTime() 简单

3.

 ~x 大致等于 -(x+1) 

~42; // -(42+1) ==> -43

4.

var a = "Hello World";

if(a.indexOf("ol") == -1){

    //没有匹配

}

这里是指用-1作为失败时的返回值,这些细节应该被屏蔽。

var a= "Hello World";

~a.indexOf("lo"); // -4 真值

if (~a.indexOf("of")) {  //true

    //找到匹配

}

~a.indexOf("ol"); //  0 <–假值

!~a.indexOf("ol"); // true

if(!~a.indexOf("ol")){ //true

    //没有匹配!

}  

5.

~~49.6

~~x 能对小数进行截取,取代Math.floor(xxx),但需要注意负数的情况

~~-49.6 // -49,    ~~中的第一个~执行ToInt32并反转字位,然后第二个~再进行一次字位反转,即将所有字位反转回原值,最后得到仍然是ToInt32的结果

Math.floor( -49.6 ) //-50

6.

[] + {} //[Object object]   "" + [Object object] 

{} + [] //0     {}被当作一个独立的空代码快,不执行任何操作。  代码块结尾不需要分号, 最后+[] 将[]显示强制类型转换

7.

true || false && false;  //true
(true || false) && false;  //false 
true || (false && false);  //true

这说明&&运算符优先于||执行

8.

function foo( a = 42, b = a+1) {
    console.log(
        arguments.length, a, b,
        arguments[0], arguments[1]
    )
}
foo();                             //0 42 43 undefined undefined
foo( 10 );                       //1 10 11 10 undefined
foo( 10, undefined );    //2 10 11 10 undefined
foo( 10, null );              //2 10 null 10 null

在ES6中,虽然参数a和b都有默认值,但是函数不带参数时,arguments数组为空.

如果向函数传递undefined值,则arguments数组中会出现一个值为undefined的单元

9.

<script>foo();</script>

<script>

    function foo() { .. }

</script>

报错,不会进行变量提升

10.

在调试的过程中,有可能对象在console.log(…)语句之后被修改,看到了意料之外的结果,要意识到 这可能是I/O的异步造成的,可以用JSON.stringify()快照一次

第四章

1.Promise中,多次调用reject或resovles,只有第一次有效

new Promise((resovles, reject)=>{
        //something
        resovies(); //只有第一次有效
        resovies(); //无效
})

12.Promise中,只能返回第一个参数

new Promise((resovles, reject)=>{
        //something
        resovies(a, b, c); //只返回a
})

13. 如果Promies中发生错误,则不往下执行,而是返回一个promise,包含错误信息

var p = new Promise(()=>{xxxx});
var p2 = p.then(()=>{
    make some error code
    //不会报错,也不会运行到下一行
    some code
},()=>{
    //不会执行到这里
})
p2.then((e)=>{
    console.log(e) //e就算错误信息
})

14. Promise的局限性有6个

    1.Promise链中的错误信息很容易被无意中默默忽略掉

    2.只接受单一值返回

    3.单决议 // 就是 resolve或rejuect只能运行一次

    4.惯性 //就是通常要封装request之类的

    5.无法被取消

    6.性能稍微低一点点

15. 

function *something(){
    while(true){
        console.log(xxxx)    
    }
    finally{
        console.log("cleaning up!")
    }
} 
var it = something();
for(var v of it) {
    console.log(v);
    if(v > 500){
        it.return("end").value;
    }
}

调用it.return(…)之后,它会立即终止生成器,运行finall语句

16.

function *foo(){
    console.log( "*foo() starting" );
    yield 3;
    yield 4;
    console.log( "*foo() finished");
}
function *bar() {
    yield 1;
    yield 2;
    yield *foo(); // yield委托
    yield 5;
}
var it = bar();
it.next().value;   //1
it.next().value;   //2
it.next().value;   //*foo() starting   注意观察这里,*bar() 把自己的迭代控制委托给了*foo()
                      //3
it.next().value;   //4
it.next().value;   //*foo() finished
                   // 5

第五章

1.尾调用优化

function bar(y){
    return foo( y + 1);  //尾调用
}
function baz(){
    return 1 + bar( 40 );  //非尾调用
}

发表评论