温故知新:Javascript 杂记
目录
温故而知新,复习后才发现很多基础掌握得不牢固。
数据类型 #
typeof检查输入参数机器码后三位,000代表object类型,而null恰好用全 0 表示。
typeof null; // object
typeof对于未实现[[Call]]方法的引用类型返回object,已实现该方法的则返回function。
typeof Array; // function
- 简单类型和作为
object的复杂类型:
typeof "hello"; // string
typeof new String("hello"); // object
instanceof判断实例时向上追踪原型链。
[] instanceof Array
[] instanceof Object
- 比
typeof更准确的类型判断:
Object.prototype.toString.call([]); // Array
- 逻辑运算符与非布尔类型混用:
5 || 0; // 5
0 || "a"; // 'a'
5 && 0; // 0
- 拆箱时调用
toPrimitive()方法:- 如果是原始类型值则直接返回;
- 否则调用
.valueOf(),如果返回值是原始类型值则返回; - 否则调用
.toString(),返回得到的string。
[].valueOf() // []
[].toString() // ''
{}.valueOf() // {}
{}.toString() // [object Object]
[] + [] // ''
[] + {} // [object Object]
- 部分浏览器中将
{}视作空代码块:
{
}
+[]; // 0
深浅拷贝 #
浅拷贝 #
- 遍历赋值
for (var i in origin) {
clone[i] = origin[i];
}
Object.create,实际会拷贝到clone的_proto_上:
clone = Object.create(origin);
深拷贝 #
- 借助 JSON:
clone = JSON.parse(JSON.stringify(origin));
Object.assign,与空对象合并:
clone = Object.assign({}, origin);
编码 #
escape不会对字母、数字以及*@-_+./进行编码,对其他所有字符均进行编码,目前已废弃。encodeURI将输入参数视作完整的 URI,不会对字母、数字以及,/?:@&=+$#进行编码,对其他所有字符均进行编码。encodeURIComponent将输入参数视作 URI 的一部分,不会对字母、数字以及-_.!~*'()进行编码,对其他所有字符均进行编码。
函数与作用域 #
- 函数与变量的声明会被提前到所在作用域最前面。变量赋值不会被提前。
- 闭包:
function foo() {
var a = 2;
function bar() {
console.log(a);
}
return bar;
}
var baz = foo();
baz(); // 2
- 一个经典例子,
timer访问到的i是循环结束后的全局作用域中的i:
for (var i = 1; i <= 5; ++i) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
} // 6 6 6 6 6
解决方案:
- 用 IIFE 创建作用域
for (var i = 1; i <= 5; ++i) {
(function (j) {
setTimeout(function timer() {
console.log(j);
}, j * 1000);
})(i);
} // 1 2 3 4 5
- 借助
let的特性
for (let i = 1; i <= 5; ++i) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
} // 1 2 3 4 5
- 类数组转为
Array:
arr = Array.prototype.slice.apply(args);
实际上,调用 apply、call、bind 等方法均会对 this 进行显式绑定。
this的默认绑定:内部函数(或者其他类似的找不到this指向的情况)中的this指向window(严格模式下指向undefined):
var a = {
b: 1,
getB: function () {
function c() {
console.log(this.b); // undefined
}
c(); // window.c()
console.log(this.b); // 1(隐式绑定)
},
};
a.getB();
同理,回调函数也常常会丢失 this。
new调用的所谓 “构造函数” 实际上是对新创建的对象进行初始化的一种“构造调用”,步骤如下:- 创建新对象;
- 执行
[[Prototype]]连接; - 绑定
this,即所谓的new绑定; - 如果调用的函数没有返回对象,则返回该新对象
- 优先级:
new绑定 > 显式绑定 > 隐式绑定 > 默认绑定 - 箭头函数自动继承外层作用域的
this,且无法修改。
其他 #
sort默认将元素转为字符串后升序排序。
var arr = [2, 13, 3, 11, 5, 7];
arr.sort(); // [11,13,2,3,5,7]