javascript
模拟实现
function promiseAll(promises) {
return new Promise((resolve, reject) => {
let res = []
let count = 0
for (let i=0; i<promises.length; i++) {
promises[i].then(r => {
res[i] = r
count++
if (count === promises.length) {
resolve(res)
}
}).catch(err => {
res[i] = err
count++
if (count === promises.length) {
reject(res)
}
})
}
})
}
function deepClone(obj){
return JSON.parse(JSON.stringify(obj))
}
function deepClone(obj) {
return new Promise(resolve => {
let { port1, port2 } = new MessageChannel()
port2.onmessage = e => {
resolve(e.data)
}
port1.postMessage(obj)
})
}
function deepClone(obj) {
let objCpy = {}
for (let k in obj) {
if (typeof obj[k] === 'function') {
objCpy[k] = obj[k].bind()
} else if (typeof obj[k] !== 'object' || obj[k] === null) {
objCpy[k] = obj[k]
} else if (obj[k] instanceof Array) {
let arr = deepClone(obj[k])
arr.length = obj[k].length
objCpy[k] = Array.from(obj[k])
} else {
objCpy[k] = deepClone(obj[k])
}
}
return objCpy
}
let person = {
name: 'xm',
age: 18,
fav: ['play', 'study', 'movies']
}
let p = Object.create(person)
function Animal(name) {
this.name = name
}
Animal.prototype.eat = function () {
console.log('Animal eat')
}
function Fish(name, age) {
Animal.apply(this, arguments)
this.age = age
}
Fish.prototype = new Animal()
Fish.prototype.constructor = Fish
Fish.prototype.swim = function () {
console.log('Fish swim')
}
fishc = new Fish("甲鱼", 18)
fishc.eat()
fishc.swim()
function Animal(name) {
this.name = name
}
Animal.prototype.eat = function () {
console.log('Animal eat')
}
function Fish(name, age) {
Animal.apply(this, arguments)
this.age = age
}
Fish.prototype = Object.create(Animal.prototype, {
constructor: {
value: Fish,
enumerable: false,
writable: true,
configurable: true
})
Fish.prototype.swim = function () {
console.log('Fish swim')
}
fishc = new Fish("甲鱼", 18)
fishc.eat()
fishc.swim()
理论
- 几种常见for循环的区别与不足之处 (for,for of,for in ,foreach)
- for: 常规循环,需要使用计次变量
- for of: 遍历对象的value,需要被遍历对象部署iterator接口
- for in: 遍历对象的key,包括在原型链上添加的属性
- forEach: 只能遍历数组的value
- 什么是深拷贝,什么是浅拷贝?
- 深拷贝:层层拷贝对象的真实值,而不是拷贝引用,修改拷贝后的对象不影响原对象
- 浅拷贝:只拷贝了对象的一层属性,如果属性为引用类型,则修改拷贝的对象后会影响原对象
- generator与async/await有什么关系
- generator
- 生成器,声明时使用 function*,执行时返回一个生成器对象
- 生成器对象每次调用 next 方法会返回 yield 抛出的数据
- 调用 next 方法传入的参数可以被 yield 返回
- async/await
- 是 ES7 引入的,为了更方便的书写异步代码
- 是通过使用generator 跟 promise实现的
async function fn(args) {
}
function fn(args) {
return spawn(function* () {
});
}
function spawn(genF) {
return new Promise(function(resolve, reject) {
const gen = genF();
function step(nextF) {
let next;
try {
next = nextF();
} catch(e) {
return reject(e);
}
if(next.done) {
return resolve(next.value);
}
Promise.resolve(next.value).then(function(v) {
step(function() { return gen.next(v); });
}, function(e) {
step(function() { return gen.throw(e); });
});
}
step(function() { return gen.next(); });
});
}
- 如何实现generator的自动调用
function run(gen) {
var g = gen();
function next(data) {
var res = g.next(data);
if(res.done) return res.value;
res.value.then(function (data) {
next(data);
});
}
next();
}
- new一个对象做了什么(讲述一下new的原理)
- 创建一个空对象,作为将要返回的对象实例。
- 将这个空对象的原型,指向构造函数的prototype属性。
- 将这个空对象赋值给函数内部的this关键字。
- 开始执行构造函数内部的代码。
- 如果构造函数内部有return语句,而且return后面跟着一个对象,new命令会返回return语句指定的对象;否则,就会不管return语句,返回this对象。
事件相关
- 什么是事件委托
- 利用事件冒泡机制,将对事件的处理函数绑定在事件发生元素的祖先元素上统一进行处理
- 事件的回调函数 e.target与.currentTarget分别指向谁
- e.target 是事件发生的实际元素
- e.currentTarget 是当前在处理事件的函数所绑定的元素