本篇绪论
1,闭包
2,深浅拷贝
3,防抖、节流
1,闭包
闭包的定义很简单:函数 A 返回了一个函数 B,并且函数 B 中使用了函数 A 的变量,函数 B就被称为闭包。
function A() {
let a = 100
function B() {
console.log(a)
}
return B()
}
A() // 100
经典面试题:
1, for (var i = 0; i <= 5; i++) {
setTimeout(function () {
console.log(i)
}, i * 1000)
}
// 6 6 6 6 6 6
因为setTimeout是异步函数,所以回把循环全部执行完成,这时候 i 就是 6 了,所以输出6个6
如何改动能使打印出的是0 1 2 3 4 5呢
解决办法:
1,第一种方法使用闭包
for (var i = 0; i <= 5; i++) {
(function (j) {
setTimeout(function () {
console.log(j)
}, j * 1000)
})(i)
}
2, 第二种方法是使用setTimeout的第三个参数
for (var i = 0; i <= 5; i++) {
setTimeout(function timer(j) {
console.log(j)
}, i * 1000, i)
}
3,第三种方法使用let
for (let i = 0; i <= 5; i++) {
setTimeout(function () {
console.log(i)
}, i * 1000)
}
2, 深浅拷贝
let a = {
age: 100
}
let b = a
a.age = 200
console.log(a) // {age: 200}
console.log(b) // {age: 200}
以上代码,如果给一个变量赋值一个对象,那么两者的值会是同一个引用,其中一个改变,另一个也会相应改变
浅拷贝
1,Object.assign()可以实现浅拷贝
let a = {
num: 1000
}
let b = Object.assign({}, a)
a.num = 2000
console.log(a) // {num: 2000}
console.log(b) // {num: 1000}
2,使用展开运算符...
let a = {
num: 1000
}
let b = {...a}
a.num = 2000
console.log(a) // {num: 2000}
console.log(b) // {num: 1000}
3, Array.prototype.slice
let a = [{num: 1000}]
let b = a.slice(0)
console.log(a) // [{num: 1000}]
console.log(b) // [{num: 1000}]
深拷贝
可以通过JSON.parse(JSON.stringify(obj))实现
let a = {
age: 1000,
jobs: {
first: 'FE'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'Native'
console.log(a) // {age: 1000, jobs: {first: 'Native'}}
console.log(b) // {age: 1000, jobs: {first: 'FE'}}
但是该方法是有局限性的:
- 会忽略 undefined
- 不能序列化函数
- 不能解决循环引用的对象
let obj = {
a: 10,
b: {
c: 20,
d: 30
}
}
obj.c = obj.b
obj.e = obj.a
obj.b.c = obj.c
obj.b.d = obj.b
obj.b.e = obj.b.c
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)

这个循环引用对象,不能通过该方法深拷贝。
在遇到函数或者undefined的时候,该对象也不能正常的序列化:
let a = {
age: undefined,
sayHi: function () {},
name: 'xiaowang'
}
let b = JSON.parse(JSON.stringify(a))
console.log(a)
console.log(b)

以上代码,该方法会忽略掉函数和undefined
网友评论