跳到主要内容

核心概念✅

下面代码中 a 在什么情况下会打印 1 ?

const a = {
// 实现 a 对象
}
// 使得此处等式成立
if (a == 1 && a == 2 && a == 3) {
console.log(1)
}
答案
const a = {
i: 1,
toString: function () {
return this.i++
}
}
// eslint-disable-next-line
if (a == 1 && a == 2 && a == 3) {
console.log(1)
}

在这个例子中,a 被定义为一个对象,有一个属性 i 初始化为 1,同时重写了 toString 方法,在每次调用时返回 i 的值,并且每次返回后将 i 自增。这样在比较 a 是否等于 1、2、3 的时候,会依次调用 a.toString() 方法,得到的结果就是满足条件的 1,依次打印出来。

深拷贝和浅拷贝

实现一个 sum 函数,支持任意个参数的累加,在 console.log 时输出结果?

// example1
console.log(sum(1)(2)(3, 4)) // 10

// example2
console.log(sum(1, 2, 3, 4)) // 10
答案
function sum (...args) {
let total = args.reduce((a, b) => a + b, 0)
function inner (...rest) {
total += rest.reduce((a, b) => a + b, 0)
return inner
}
inner.toString = inner.valueOf = () => total
inner[Symbol.toPrimitive] = () => total
return inner
}
// example1
console.log(+sum(1)(2)(3, 4)) // 10

// example2
console.log(+sum(1, 2, 3, 4)) // 10

模拟new操作

答案

在 JavaScript 中,new 关键字的核心作用是:

  1. 创建一个新的空对象;
  2. 将新对象的原型指向构造函数的 prototype
  3. 将构造函数内部的 this 绑定到新对象;
  4. 执行构造函数逻辑;
  5. 如果构造函数返回一个对象,则返回该对象,否则返回新创建的对象。

自定义实现时需注意:

  • 必须正确设置原型链;
  • 需处理构造函数显式返回对象的情况;
  • 不能省略 this 绑定和参数传递。

实现代码如下:

function myNew (constructor, ...args) {
// 1. 创建一个新对象,原型指向构造函数的 prototype
const obj = Object.create(constructor.prototype)
// 2. 执行构造函数,将 this 绑定到新对象
const result = constructor.apply(obj, args)
// 3. 返回构造函数返回的对象(如果是对象),否则返回新对象
return (typeof result === 'object' && result !== null) ? result : obj
}

使用示例:

function Person (name, age) {
this.name = name
this.age = age
}
Person.prototype.sayHi = function () {
console.log(`Hi, I'm ${this.name}, ${this.age} years old.`)
}

const p = myNew(Person, 'Alice', 20)
p.sayHi() // Hi, I'm Alice, 20 years old.

实现链式调用 ?

答案

链式调用是指多个方法可以连续调用,每个方法返回当前对象,以便可以继续调用其他方法。实现链式调用通常需要在每个方法中返回 this,以保持对当前对象的引用。

class Chainable {
constructor (value) {
this.value = value
}

add (num) {
this.value += num
return this
}

subtract (num) {
this.value -= num
return this
}

multiply (num) {
this.value *= num
return this
}

divide (num) {
this.value /= num
return this
}

getValue () {
return this.value
}
}
const result = new Chainable(10)
.add(5)
.subtract(2)
.multiply(3)
.divide(2)
.getValue()
console.log(result) // 19.5
48%