1. JS值类型与引用类型的区别
1. 值类型/简单数据类型: string、number、boolean、undefined、null
值存在栈中 赋值拷贝也是栈数据 修改拷贝数据对原数据没有影响
1 2 3 4
| let num1 = 10 let num2 = num1 num2 = 20 console.log(num1, num2)
|
2.引用类型/复杂数据类型: Array、function、Object
栈中存储地址 堆中存储数据 赋值时拷贝的是栈地址 修改拷贝数据(堆)对原数据有影响
1 2 3 4
| let num3 = [1,2] let num4 = num3 num4[0] = 10 console.log(num3, num4)
|
3. 变量修改 栈与堆的区别
1 2 3
| num4 = 10
console.log(num3, num4)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| let num = 10 function fn1() { num = 20 } fn1() console.log(num)
let arr = [1,2,3] function fn2(arr) { arr = 100 } fn2() console.log(arr)
function fn3(arr) { arr[0] = 100 } fn3(arr) console.log(arr)
function fn4() { arr[0] = 100 } fn4() console.log(arr)
|
2. 字符串方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| let n1 = 'red, blue' console.log(n1.split(','))
let n2 = '蔡徐坤' console.log(n2.replace('蔡', '嗯'))
console.log(n2.replace('蔡', ''))
console.log(n2.replace('徐坤', '先生'))
let n3 = '你是傻逼' console.log(n3.replace('傻逼', '**'))
|
3. 数组的增删改查方法以及返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| let arr = [1,2,3,4] 1. 新增数组
arr.push(11, 22) arr.unshift(0) 2. 删除数组
arr.pop() arr.shift() 3. 查询数组
console.log(arr.slice(1, 3)) console.log(arr.splice(1, 1)) console.log(arr) 4. 数组.join('分隔符') 将数组每一个元素用分隔符拼接成字符串
console.log(arr.join('|')) 5. 数组.reverse 翻转数组(修改原数组) console.log(arr.reverse(arr))
let a = '蔡徐坤' console.log(a.split('').reverse('').join('')) 6. .sort 数组排序 按照ASCII编码顺序排序 console.log(arr.sort())
let obj = [ {name: '华为', age: 10}, {name: '小米', age: 40}, {name: '苹果', age: 30} ] obj.sort((a, b) => { return a.age - b.age }) console.log(obj)
|
4. 数组的遍历方法
1. 数组forEach 是没有return的也没有返回值
- 应用场景: 修改数组的每一个元素值
- 金典面试题: 如何终止forEach? (try-catch)
1 2 3 4 5 6 7
|
let arr = ['小米','苹果','华为'] arr.forEach(function (item, index) { console.log(item) console.log(index) })
|
2. 数组map
- return 会新数组返回值
- 应用场景: 数组的转换: 根据数组的元素, 得到一个全新的数组
- 由于map创建一个新数组, 在没有使用返回的数组情况下调用它是不恰当的:
- 应该使用forEach或for…of作为代替
1 2 3 4 5
| let arr = [1,2,3] arr.map(i => { console.log(i) console.log({name: i}) })
|
2. 数组filter
- return true: 满足筛选条件的 放入新数组中
- return true: 不满足筛选条件的 不放入新数组
- filter方法自身返回值: 满足条件的新数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let n1 = [10, 15, 20, 30] let fn = n1.filter(function (a, b) { console.log(a) console.log(b) return a >= 20 })
console.log(fn)
let say = n1.filter(item => item >= 40) console.log(say)
|
3. 数组 indexOf(): 查找元素下标(只能找值类型下标)
4. 数组 findIndex(): 查找元素下标(只能找引用类型下标)
- return true: 找到了, 循环结束, 返回当前元素下标
- return false: 没找到, 循环继续, 最终返回-1
- findIndex方法自身返回值: 元素下标 || -1
- 应用场景: 找到对象元素中 元素的下标
1 2 3 4 5 6 7 8 9
| let arr = [ {name: '小东', age: 1}, {name: '小刚', age: 2}, {name: '小明', age: 3} ] let n1 = arr.findIndex((item, index) => { return item.age == 2 }) console.log(n1)
|
5. 数组find和findIndex作用是一样的, 返回值是元素本身
- 应用场景: 修改对象数组中某一个对象属性
1 2 3 4 5 6
| let n2 = arr.find((item, index) => { return item.age == 2 console.log(item) }) console.log(n2) console.log(n2.age *= 0.1)
|
6. 数组reduce方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| let n4 = [1,2,3,4]
let n5 = n4.reduce(function (a, b) { return a + b }) console.log(n5)
let n6 = n4.reduce(function (a, b) { return a + b }, 10) console.log(n6)
let n7 = n4.reduce((a, b) => a + b, 10) console.log(n7)
let n8 = [1,2,3] let n9 = n8.reduce((a, b) => a + b) console.log(n9)
let n10 = [1,2] let n11 = n10.reduce((a, b) => a + b, 10) console.log(n11)
|
5. 箭头函数和普通函数的区别
1. function函数的this指向: 谁调用函数, this就指向谁
- 普通函数: fn() this指向window
- 对象方法: fn.方法名() this指向对象
- 构造函数: new 函数名 this指向实例对象
1 2 3 4 5 6 7 8 9
| function fn() { console.log(this) } fn() let obj = { a: fn } obj.a() new fn()
|
2. 箭头函数this: 箭头函数没有this 本质是访问上级作用域this
- 箭头函数不能作为构造函数(报错)
- 箭头函数不能使用上下文修改this(call、apply、bind)
- 箭头函数不能使用arguments(报错)
1 2 3 4
| let f = () => { console.log(this) } f.call('你好')
|
3. 经典面试题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| let obj1 = { name: '小明', age() { function fn1() { console.log(this) } fn1() let fn2 = () => { console.log(this) } fn2() }, say: () => { function fn1() { console.log(this) } fn1() let fn2 = () => { console.log(this) } fn2() } } obj1.age() obj1.say()
|
6. 原型与原型链
- 对象原型__proto__的意义是为对象成员查找机制提供一条路线
- 原型链是一个查找规则
- 可查找一些属性和方法 沿着一条路走
- 先看当前原型对象上面有没有
- 果没有再往上一层的原型对象查找
- 如果有 就可使用
- 往上查找最终找到Object为止(null)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| function fn() {
} let n1 = new fn()
console.log(n1.__proto__ == fn.prototype)
console.log(fn.prototype.__proto__ == Object.prototype)
console.log(Object.prototype.__proto__)
console.log(n1 instanceof fn)
console.log(n1 instanceof Object)
console.log(n1 instanceof Array)
console.log([1,2,3] instanceof Array)
console.log(Array instanceof Object)
|