八股文-js

欢迎阅读 js 八股文

📌 js

Q1:如何确认this的值

A:
1、全局执行环境中 this指向window
2、函数内部-this指向调用者

1
2
3
4
function func(){
console.log(this) //window
}
func()

1
2
3
4
5
function func(){
'use strict'
console.log(this) //undefined
}
func()

3、对象方法调用-this指向对象
1
2
3
4
5
6
7
const food= {
name: 'apple',
eat() {
console.log(this)
}
}
food.eat() //food对象

Q2:如何指定this的值

A:
1、调用时指定
call

1
2
3
4
5
6
7
8
function func(num1,num2){
console.log(this)
console.log(num1,num2)
}
const person = {
name: '张三'
}
func.call(person,1,2) //name: '张三' 1 2

apply(传入数组)
1
func.apply(person,[3,4])  //name: '张三'   3  4

2、创建时指定
bind

1
2
const bindFunc = func.bind(person,666)
bindFunc(888) //name: '张三' 666 888

箭头函数
1
2
3
4
5
6
7
8
9
const food= {
name: 'apple',
eat() {
console.log(this)
setTimeout(()=>{
console.log(this) //food对象
},1000);
}
}

Q3:手写call方法

A:

1
2
3
4
5
6
7
Function.prototype.myCall = function(thisarg, ...args) {
const key = Symbol('key')
thisarg[key]= this //用[]解析
const res=thisarg[key](...args)
delete thisarg[key]
return res
}

Q4:手写apply方法

A:

1
2
3
4
5
6
7
Function.prototype.myApply = function(thisarg, args) {
const key = Symbol('key')
thisarg[key]= this //返回绑定this的新函数
const res =thisarg[key](...args)
delete thisarg[key]
return res
}

Q5:手写Bind方法

A:

1
2
3
4
5
6
Function.prototype.myBind = function(thisarg, ...args) {
return(...reargs)=>{
return call(thisarg, ...args, ...reargs)
}
}

Q6:javascript继承

A:
static静态

私有

Q7:函数柯里化

A:
把接受多个参数的函数变换成接受一个单一参数的函数,并且返回接受余下参数而且返回结果的新函数的技术

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let nums=[]
function sum(...args){
nums.push(...args)
if (nums.length>=5){
const res=nums.slice(0,5).reduce((p,v)=>p+v,0)
nums=[]
return res
}else{
return sum
}
}


const typeOftest=type=>thing=>typeof thing===type

const isString=typeOftest('string')

Q8:基本的数据类型介绍,及值类型和引用类型的理解

A:

1. JavaScript 中的数据类型

JS 中共有 8 种基础数据类型

  1. Undefined
  2. Null
  3. Boolean
  4. Number
  5. String
  6. Object
  7. Symbol(ES6 新增)
  8. BigInt(ES6 新增)

2. ES6 新增的数据类型

  • Symbol

    • 代表独一无二的值。
    • 常用来定义对象的唯一属性名,避免属性名冲突。
  • BigInt

    • 可以表示任意大小的整数。
    • 解决了 Number 类型最大安全整数 2^53 - 1 的限制。

3. 值类型 vs 引用类型

  • 值类型(基本数据类型)

    • 存储在 栈内存 中。
    • 每个变量都有独立的存储空间。
    • 包括:UndefinedNullBooleanNumberStringSymbolBigInt
  • 引用类型

    • 存储在 堆内存 中,变量存的是引用地址。
    • 多个变量可能指向同一个对象。
    • 包括:Object(如 ArrayFunctionDate 等)。

4. 数据类型判断方法对比

1. typeof

  • 优点:能判断所有基本数据类型和函数。
  • 缺点:对 null、对象、数组返回的都是 object,无法精确区分。

2. instanceof

  • 作用:判断对象是否是某个构造函数的实例。
  • 适用:对象类型。
  • 局限:不能判断基本数据类型。
  • 原理:判断某对象的原型链上,是否能找到指定构造函数的 prototype

示例:

1
2
3
4
[] instanceof Array;       // true
{} instanceof Object; // true
new Date() instanceof Date; // true
123 instanceof Number; // false (基本类型不能判断)

2. Object.prototype.toString.call()

  • 作用:精确判断所有数据类型。
  • 适用:基本数据类型 + 内置对象类型(Array、Date、Error 等)。
  • 局限:不能判断基本数据类型。
  • 原理:返回 “[object Type]” 字符串。。

示例:

1
2
3
4
5
6
7
8
9
Object.prototype.toString.call(2); // "[object Number]"
Object.prototype.toString.call(""); // "[object String]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(Math); // "[object Math]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(function () {}); // "[object Function]"

5. 手写深拷贝

示例:

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 自定义高性能的遍历方法
function forEach(arr, iterator) {
let index = 0
const len = arr.length

while (index < len) {
iterator(arr[index], index)
index++
}

return arr
}

/**
* 深拷贝
* @param {Object} obj 要拷贝的对象
* @param {Map} map 用于存储循环引用对象的地址
*/
function deepClone(obj, map = new WeakMap()) {
if (typeof obj !== "object") {
return obj;
}

if (map.get(obj)) {
return map.get(obj)
}

const isArray = Array.isArray(obj) || Object.prototype.toString.call(obj) === '[object Array]'

let result = isArray ? [] : {}

map.set(obj, result)

const iteratorArr = isArray ? obj : Object.keys(oabj)
forEach(iteratorArr, (val, key) => {
if (!isArray) {
key = val
}
result[key] = deepClone(obj[key], map)
})

return result
}

const target = {
field1: 1,
field2: undefined,
field3: "ConardLi",
field4: {
child: "child",
child2: {
child2: "child2"
}
},
field5: [1, 2,3, 4],
}

target.field6 = target

console.log(deepClone(target))