实现数组的 push、filter、map 方法
js
复制代码
// push
Array.prototype.myPush = function (...args) {
const length = this.length
for (let i = 0; i < args.length; i++) {
this[this.length + i] = args[i]
}
return this.length
}
// filter
Array.prototype.myFilter = function (callback) {
const newArr = []
for (let i = 0; i < this.length; i++) {
if (callback(this[i], i, this)) {
newArr.push(this[i])
}
}
return newArr
}
// map
Array.prototype.myMap = function (callback) {
const newArr = []
for (let i = 0; i < this.length; i++) {
newArr.push(callback(this[i], i, this))
}
return newArr
}
const list = [1, 2, 3, 4, 5]
console.log(list.myPush(6)) // 6
console.log(list.myFilter((i) => i > 3)) //[ 4, 5, 6 ]
console.log(list.myMap((i) => i + 1)) // [ 2, 3, 4, 5, 6, 7 ]
js 实现红黄绿循环打印
- 用 promise 实现
js
复制代码
const task = (timer, light) =>
new Promise((resolve, reject) => {
setTimeout(() => {
if (light === 'red') {
red()
} else if (light === 'green') {
green()
} else if (light === 'yellow') {
yellow()
}
resolve()
}, timer)
})
const step = () => {
task(1000, 'red')
.then(() => task(2000, 'green'))
.then(() => task(3000, 'yellow'))
.then(step)
}
step()
- 用 async/await 实现
js
复制代码
const task = (light, timeout) => {
return new Promise((resolve) => {
setTimeout(() => resolve(console.log(light)), timeout)
})
}
const taskRunner = async () => {
await task('red', 1000)
await task('green', 2000)
await task('yellow', 3000)
taskRunner()
}
taskRunner()
手写 new
答案
function funcNew(obj, ...args) {
const newObj = Object.create(obj.prototype);
const result = obj.apply(newObj, args);
return (typeof result === 'object' && result !== null) ? result : newObj;
}
解读
先通过一个例子来理解 new 的作用吧:
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function() {
console.log(this.name);
}
const p = new Person('orange')
console.log(p.name) // 'orange'
p.sayName(); // 'orange'
代码中我们新建了一个对象 Person,它具有属性 name,且在 Person.prototype 上定义了函数 sayName。
当我们通过 new 创建一个新的实例 p 时,便同时具有了属性 p.name 和 p.sayName(),关系如下图:
知道了原理,就可以自己实现了。也就是说,自己写一个函数 funcNew(),使得 const p = new Person('orange') 和 const p = funcNew('orange') 得到的 p 完全相同,于是得到了答案中的代码。
答案中最后一行代码如何理解?
前面的例子我们只考虑了 Person 中没有返回值的情况,如有有返回值,new 一个实例将会受到 Person 中返回值的影响。比如说:
/**
* --- Person 中 return 一个对象,p 为该对象 ---
*/
function Person(name) {
this.name = name;
return {age: 35}
}
Person.prototype.sayName = function() {
console.log(this.name);
}
const p = new Person('orange')
console.log(p) // { age: 35 }
console.log(p.name) // undefined
p.sayName(); // TypeError: p.sayName is not a function
/**
* --- Person 返回非对象,return 不影响结果 ---
*/
function Person(name) {
this.name = name;
return 'free'
}
Person.prototype.sayName = function() {
console.log(this.name);
}
const p = new Person('orange')
console.log(p) // Person { name: 'orange' }
console.log(p.name) // orange
p.sayName(); // orange
上面的例子中,如果返回了一个对象,我们需要返回该对象;如果不是对象,则 return 没用,正常处理。
深拷贝
// deepClone
function deepClone(obj = {}) {
if (typeof obj !== 'object' || obj == null) {
// obj 是 null 或者不是对象和数组,直接返回
return obj;
}
let res;
if (obj instanceof Array) {
res = [];
} else {
res = {};
}
for (let key in obj) {
// 判断自身中是否包含自身属性
if (obj.hasOwnProperty(key)) {
res[key] = deepClone(obj[key])
}
}
return res;
}
// 验证
o = {a: 1, d: {c: '4'}};
res = deepClone(o);
console.log(res);
console.log(res == o);