你不知道的JavaScript

let与var的区别

作用域的问题,let变量在子作用域中独立,而var变量只存在于父级作用域。

for (let i = 0; i < 3; i ++ ) { 
        setTimeout(() => { console.log(i) }, 200); // 0 1 2
}
i // undefined

for (var i = 0; i < 3; i ++ ) { 
        setTimeout(() => { console.log(i) }, 200); // 3 3 3
}
i // 3

逻辑操作符

JS特性:如果在短路逻辑操作||符中遇到非布尔变量,则直接返回改变量:

false || {} // {}
null || {} // {}
undefined || {} // {}

这个特性常用来实现避免重复初始化对象变量,不过并不完美:

// 如果 $ 未定义或者值为 null、0、false...(称为falsy) , 则为其赋值,否则保留原值
const $ = $ || { /*...*/ }

如果真的需要检测变量是否已被声明并定义,即使它是null,那应该使用typeof关键字。

if (typeof $ === 'undefined') {
//...
}

要进行二进制的真假比较,使用二次取反即可:

flase || !!{} // true

Function

在JS中,函数是一种特殊的对象,Object、Array、Number、甚至Function等关键字都是内置的函数,称为构造函数,使用new关键字来创建对应的对象。

  • 构造函数的复杂性
    需要注意的是构造函数和普通函数一样是有返回值的,因此构造函数比较特殊,有两条返回路径,一方面可以在构造函数中可以使用this['key'] = value来对对象添加属性,另一方面可以像正常函数一样返回任何对象,如果返回一个Object,还会屏蔽new调用的返回值。
    如果不使用new关键字调用构造函数,可能会污染全局空间。
  • 函数的属性
    length: 函数声明的形式参数的个数
    caller: 返回调用者
    arguments: 调用者传入的参数,是一个需要迭代的对象。是一个可以直接在函数中使用的关键字。
    arguments.callee: 常用于匿名函数的递归调用 arguments.callee.caller即为当前函数的调用者
    call()、apply():函数复用,调用函数时,用指定的对象替换函数的this值,并用指定的数组替换函数的参数,apply(_this, [...arguments])等价于call(_this, ...arguments)
    bind(thisArg, [...argArray]): 产生一个this值不同, 前几个参数固定的新函数, 这个函数的this值是thisArg, argArray是固定的参数, 多余的参数依次填入.
  • 构造函数的原型对象

通过字符串模板调用函数

function mySkills(strs, name, skillA, skillB) {
    console.log(strs);
    console.log(`${name} is a ${skillA} Programmer.`)
    console.log(`${name} is a ${skillB} Programmer.`)
}

var info = `${"Zhang"}'s skills is ${"Java"} and ${"C++"}.`;
console.log(info);

mySkills `${"Zhang"}'s skills is ${"Java"} and ${"C++"}.`;

输出:

Zhang's skills is Java and C++.
[ '', "'s skills is ", ' and ', '.' ]
Zhang is a Java Programmer.
Zhang is a C++ Programmer.

传播语法 Spread Syntax : ...

扩展语法允许将可迭代的对象(例如数组表达式或字符串)扩展到期望零个或多个参数(用于函数调用)或元素(用于数组文字)的位置,或将对象表达式扩展在零个或多个实体的位置键值对(用于对象文字)是必需的。

function sum(x, y, z) {
  return x + y + z;
}

const numbers = [1, 2, 3];

console.log(sum(...numbers));
// expected output: 6

console.log(sum.apply(null, numbers));
// expected output: 6

setTimeout 和 setInterval

  1. 它们的第一个参数可以使用字符串, 就像使用eval那样, this指向window

实验中的特性

  • 共有类字段
    该字段将挂载到实例上, 而不是在原型链中, 即不在实例的构造器的原型中, 而是一个新的对象.
    这对于箭头函数非常有用, 可用于React中在JSX中设置DOM监听器.
<div id="app">
    <h1>Hello</h1>
</div>
<script>
    class A {
        foo = () => { // Look at there
            console.log(this);
        };
    }

    app.addEventListener('click', new A().foo); // 点击将打印A实例, 而不是div app
</script>

END

原文地址:https://www.cnblogs.com/develon/p/12257700.html