1. 基本类型和引用类型的区别?
主要在数据存储方式上的区别:基本类型的数据直接存储在栈内存中,而引用类型的数据在栈中存储的是一个地址,地址指向堆内存中的数据。
为什么采取这种方式来存储?因为引用类型的数据可能会非常大,复制值过程会非常慢,非常影响性能。
2. 栈内存和堆内存的区别的区别?
栈
- 有序性:后进先出的数据结构
- 速度快:内存分配和释放的速度非常快
- 内存大小:较小
堆
- 无序性:动态分配内存,管理复杂对象
- 速度慢:由于需要处理复杂的数据结构,内存分配和释放的速度较慢
- 内存大小:较大,需要存储复杂的和大量的数据
3. 手写深拷贝
const person = {
name: 'zs',
address: {
city: 'wuhu'
}
}
const person2 = deepClone(person)
person2.address.city = 'hefei'
function deepClone(obj) {
if(typeof obj !== 'object' || obj == null) {
return obj
}
let result = obj instanceof Array ? [] : {}
for(let key in obj) {
if(obj.hasOwnProperty(key)) {
// 递归
result[key] = deepClone(obj[key])
}
}
return result
}
console.log(person)
4. 原型和原型链
5. 闭包
概念
闭包(Closure)是指有权访问另一个函数作用域中的变量的函数,简单来说,当一个函数内部定义的函数可以访问外部函数的变量时,就形成了闭包。
表现
- 函数作为参数被传递
function print(fn) {
let a = 200
fn()
}
const a = 100
function fn() {
console.log(a)
}
print(fn) // 100
- 函数作为返回值被返回
function create() {
let a = 100
return function () {
console.log(a)
}
}
const fn = create()
const a = 200
fn() // 100
自由变量的查找是在函数定义的地方向上级作用域查找,不是在执行的地方。
应用
- 能够保存函数作用域内的变量,即使外部函数已经执行完毕,闭包仍能访问和操作这些变量
function outerFunction() {
let count = 0
return function () {
count++
console.log(count)
}
}
let increment = outerFunction()
increment() // 1
- 可以实现私有变量和方法
function createCounter() {
let privateCount = 0
return {
increment: function() {
privateCount++
return privateCount
},
getCount: function() {
return privateCount
}
}
}
let counter = createCounter()
counter.increment()
- 在循环中创建异步操作时,闭包可以帮助保留正确的变量值
for (let i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i)
}, 1000)
}
for (let i = 0; i < 5; i++) {
(function (j) {
setTimeout(function () {
console.log(j)
}, 1000)
})(i)
}
6. this的使用
- this取什么值,是在函数执行的时候确定的,不是在定义的时候确定的
- 箭头函数没有自己的this
function fn1() {
console.log(this)
}
fn1() // window
fn1.call({ x: 100 }) // { x: 100 }
const fn2 = fn1.bind({ x: 200 })
fn2() // { x: 200 }
const zs = {
name: '张三',
study() {
console.log(this)
},
code() {
setTimeout(function () {
console.log(this)
})
},
code2() {
setTimeout(() => {
console.log(this)
})
}
}
zs.study() // zs对象
zs.code() // window
zs.code2() // zs对象
class People {
constructor(name) {
this.name = name
}
study() {
console.log(this)
}
}
const ls = new People('ls')
ls.study() // ls对象