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
- 它们的第一个参数可以使用字符串, 就像使用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>