温故知新:Javascript 杂记

温故而知新,复习后才发现很多基础掌握得不牢固。

数据类型

  1. typeof 检查输入参数机器码后三位,000 代表 object 类型,而 null 恰好用全 0 表示。
1
typeof null // object
  1. typeof 对于未实现 [[Call]] 方法的引用类型返回 object ,已实现该方法的则返回 function
1
typeof Array // function
  1. 简单类型和作为 object 的复杂类型:
1
2
typeof 'hello' // string
typeof new String('hello') // object
  1. instanceof 判断实例时向上追踪原型链。
1
2
[] instanceof Array
[] instanceof Object
  1. typeof 更准确的类型判断:
1
Object.prototype.toString.call([]) // Array
  1. 逻辑运算符与非布尔类型混用:
1
2
3
5 || 0 // 5
0 || 'a' // 'a'
5 && 0 // 0
  1. 拆箱时调用 toPrimitive() 方法:
    1. 如果是原始类型值则直接返回;
    2. 否则调用 .valueOf(),如果返回值是原始类型值则返回;
    3. 否则调用 .toString(),返回得到的 string
1
2
3
4
5
6
[].valueOf() // []
[].toString() // ''
{}.valueOf() // {}
{}.toString() // [object Object]
[] + [] // ''
[] + {} // [object Object]
  1. 部分浏览器中将 {} 视作空代码块:
1
2
3
{
}
;+[] // 0

深浅拷贝

浅拷贝

  1. 遍历赋值
1
2
3
for (var i in origin) {
clone[i] = origin[i]
}
  1. Object.create,实际会拷贝到 clone_proto_ 上:
1
clone = Object.create(origin)

深拷贝

  1. 借助 JSON:
1
clone = JSON.parse(JSON.stringify(origin))
  1. Object.assign,与空对象合并:
1
clone = Object.assign({}, origin)

编码

  1. escape 不会对字母、数字以及 *@-_+./ 进行编码,对其他所有字符均进行编码,目前已废弃。
  2. encodeURI 将输入参数视作完整的 URI,不会对字母、数字以及 ,/?:@&=+$# 进行编码,对其他所有字符均进行编码。
  3. encodeURIComponent 将输入参数视作 URI 的一部分,不会对字母、数字以及 -_.!~*'() 进行编码,对其他所有字符均进行编码。

函数与作用域

  1. 函数与变量的声明会被提前到所在作用域最前面。变量赋值不会被提前
  2. 闭包:
1
2
3
4
5
6
7
8
9
10
function foo() {
var a = 2
function bar() {
console.log(a)
}
return bar
}

var baz = foo()
baz() // 2
  1. 一个经典例子,timer 访问到的 i 是循环结束后的全局作用域中的 i
1
2
3
4
5
for (var i = 1; i <= 5; ++i) {
setTimeout(function timer() {
console.log(i)
}, i * 1000)
} // 6 6 6 6 6

解决方案:

  • 用 IIFE 创建作用域
1
2
3
4
5
6
7
for (var i = 1; i <= 5; ++i) {
;(function (j) {
setTimeout(function timer() {
console.log(j)
}, j * 1000)
})(i)
} // 1 2 3 4 5
  • 借助 let 的特性
1
2
3
4
5
for (let i = 1; i <= 5; ++i) {
setTimeout(function timer() {
console.log(i)
}, i * 1000)
} // 1 2 3 4 5
  1. 类数组转为 Array
1
arr = Array.prototype.slice.apply(args)

实际上,调用 applycallbind 等方法均会对 this 进行显式绑定。

  1. this 的默认绑定:内部函数(或者其他类似的找不到 this 指向的情况)中的 this 指向 window(严格模式下指向 undefined):
1
2
3
4
5
6
7
8
9
10
11
12
var a = {
b: 1,
getB: function () {
function c() {
console.log(this.b) // undefined
}
c() // window.c()
console.log(this.b) // 1(隐式绑定)
},
}

a.getB()

同理,回调函数也常常会丢失 this

  1. new 调用的所谓 “构造函数” 实际上是对新创建的对象进行初始化的一种“构造调用”,步骤如下:
    1. 创建新对象;
    2. 执行 [[Prototype]] 连接;
    3. 绑定 this,即所谓的 new 绑定;
    4. 如果调用的函数没有返回对象,则返回该新对象
  2. 优先级:new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定
  3. 箭头函数自动继承外层作用域的 this,且无法修改。

其他

  1. sort 默认将元素转为字符串后升序排序。
1
2
var arr = [2, 13, 3, 11, 5, 7]
arr.sort() // [11,13,2,3,5,7]

温故知新:Javascript 杂记

https://signormercurio.me/post/JsMisc/

Author

Mercury

Posted on

2021-07-29

Licensed under

CC BY-NC-SA 4.0

Comments

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×