1. == 和 === 有什么区别?
- 首先会判断两者类型是否相同。相同的话就是比大小了
- 类型不相同的话,那么就会进行类型转换
- 会先判断是否在对比 null 和 undefined,是的话就会返回 true
- 判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number
1 == '1'
↓
1 == 1
- 判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断
'1' == true
↓
'1' == 1
↓
1 == 1
- 判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断
'1' == { name: 'yck' }
↓
'1' == '[object Object]'
如图详解:

2.什么是闭包?
- 闭包的定义:函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么函数 B 就是闭包。
function A() {
var a = 1;
function B() {
console.log(a)
}
B()
}
A();
- 循环中使用闭包解决
var定义函数的问题
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i)
}, i * 1000)
}
第一种是使用闭包的方式
for (var i = 1; i <= 5; i++) {
(function(j) {
setTimeout(function timer() {
console.log(j)
}, j * 1000)
})(i)
}
第二种就是使用 setTimeout 的第三个参数,这个参数会被当成 timer 函数的参数传入。
for (var i = 1; i <= 5; i++) {
setTimeout(
function timer(j) {
console.log(j)
},
i * 1000,
i
)
}
第三种就是使用 let 定义 i 了来解决问题了,这个也是最为推荐的方式
for (let i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i)
}, i * 1000)
}
3.什么是浅拷贝?如何实现浅拷贝?什么是深拷贝?如何实现深拷贝?
- 浅拷贝(只解决了第一层的问题)
Object.assign 只会拷贝所有的属性值到新的对象中,如果属性值是对象的话,拷贝的是地址,所以并不是深拷贝。
1.基本类型
let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
2.复杂类型(不行)
let a = {
age: 1,
arr: [1,2,3]
};
let b = Object.assign({}, a);
a.age = 2;
a.arr.push(4)
console.log(a, b); // { age: 2, arr: [1,2,3,4] }, { age: 1, arr: [1,2,3,4] }
展开运算符 ... 来实现浅拷贝
1.基本类型
let a = { age: 1 }
let b = {...a}
a.age = 2;
console.log(a, b);// {age: 2} {age: 1}
2.复杂类型(不行)
let a = { age: 1, arr: [1,2,4]}
let b = {...a}
a.age = 2;
a.arr.push(4)
console.log(a, b);// {age: 2, arr:[1, 2, 4, 4]} {age: 1, arr:[1, 2, 4, 4]}
- 深拷贝
JSON.parse(JSON.stringify(object))
let a = {
age:1,
jobs:{
first: 'FE'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'cl';
console.log(a,b);// {age: 1, jobs: {first: "cl"}} , {age: 1, jobs: {first: "FE"}}
缺点: 1.会忽略 undefined 2.会忽略 symbol 3.不能序列化函数
let a = {
age: undefined,
sex: Symbol('male'),
jobs: function () { },
name: 'yck'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "yck"}
4.不能解决循环引用的对象
let obj = {
a: 1,
b: {
c: 2,
d: 3,
},
}
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)
- 深拷贝函数
function deepCopy(obj) {
let result = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === "object") {
result[key] = deepCopy(obj[key]);// 递归复制
} else {
result[key] = obj[key];
}
}
}
return result;
}
4.如何理解原型?如何理解原型链?
1.对于 obj 来说,可以通过 proto 找到一个原型对象,在该对象中定义了很多函数让我们来使用。
2.原型的 constructor 属性指向构造函数,构造函数又通过 prototype 属性指回原型,但是并不是所有函数都具有这个属性,Function.prototype.bind() 就没有这个属性。
3.Object 是所有对象的爸爸,所有对象都可以通过 proto 找到它
4.Function 是所有函数的爸爸,所有函数都可以通过 proto 找到它
5.函数的 prototype 是一个对象
6.对象的 proto 属性指向原型, proto 将对象和原型连接起来组成了原型链
