# 名媛云万年面试题

# 1. this 输出值

// This 对象的理解
var User = {
    count:1,
    getCount:function(){
        return this.count;
    }
}
console.log(User.getCount());
var func = User.getCount;
console.log(func());

// 1, undefined

# 2.

# 3. 跨域

如何解决跨域问题?

跨域总结

# 4. 浏览器缓存

如何设置浏览器缓存与不缓存两种。

缓存机制

# 5. 深拷贝

实现一个函数clone,可以对JavaScript中的5种主要数据类型进行值复制

function deepClone(target) {
    // is Object???
    if (typeof target == "object") {
        // array or object
        const result = Array.isArray(target) ? [] : {}
        for (let key in target) {
            if (target.hasOwnProperty(key)) {
                // 引用类型需要再次递归
                result[key] = typeof target[key] == "object" ? deepClone(target[key]) : target[key]
            }
        }
        return result
    }
    return target
}

# 6. 多层ID提取

代码实现(有几种实现)
var arr = [
    {
        id:1,
        children:[...] | null
    },
    ...
]
变量arr是一个object数组,数组元素为object,有2个属性
id:数字类型
children:有两种类型,一种是数组,结构类似于变量arr;一种是null
请用代码实现从变量arr中提取出孙子元素的id组成一个一维数组,如[1,2,3,...]
  • 循环
function getArr(arr) {
    const result = []
    if (arr && Array.isArray(arr)) {
        for (const i in arr) {
            // 第一层id
            result.push(arr[i].id)

            let children = arr[i].children
            let queue = []

            if (children) {
                queue.push(children)
            }
            let queueItem = queue.shift()

            while (queueItem) {
                queueItem.forEach(item => {
                    result.push(item.id)
                    if (item.children) {
                        queue.push(item.children)
                    }
                })
                queueItem = queue.shift()
            }
        }
    }
    return result
}
  • 递归
function getArr2(arr) {
    const result = []
    if (arr && Array.isArray(arr)) {
        (function rec(argsArr){
            argsArr.forEach(item => {
                result.push(item.id)
                let children = item.children
                if (children && Array.isArray(children)) {
                    rec(children)
                }
            })
        })(arr)
    }
    return result
}

# 7. 数组范围求和

不可变数组的范围求和
给定一个整数数组nums,计算出从i个元素到第j个元素的和(i<=j),包括nums[i]和nums[j].
例子:
const nums = Object.freeze([-2,0,3,-5,2,-1]);
sumRange(0,2) // 1
sumRange(2,5) // -1
sumRange(0,5) // -3
注意:
假定数组的值不会改变(如上面代码,nums因为Object.freeze的缘故可读不可写)
sumRange可能会被使用多次,求不同范围的值
数组规模可能很大(比如超过10000个数),注意运行时间
function sumRange(i, j) {
    const sums = []
    sums[0] = 0

    nums.forEach((item, i) => {
        sums[i + 1] = sums[i] + item
    })

    return sums[j + 1] - sums[i]
}

# 8. LazyMan实现

实现一个LazyMan,可以按照以下方式调用
LazyMan("Hank") 输出
Hi!This is Hank!

LazyMan("Hank").sleep(10).eat("dinner"); 输出
Hi! This is Hank!
// 等待10秒...
Wake up after 10
Eat dinner~

LazyMan("Hank").eat("dinner").eat("supper") 输出
Hi This is Hank!
Eat dinner~
Eat supper~

LazyMan("Hank").sleepFirst(5).eat("supper") 输出
// 等待5秒
Wake up after 5
Hi This is Hank!
Eat supper

以此类推
  • Promise + setTimeout 解法
class LazyMan {
    constructor(name) {
        this.name = name;
        this.presetTime = 0;
        this.p = Promise.resolve().then(() => {
            // sleepFirst 延迟所有操作
            if(this.presetTime > 0) {
                return this.holdon(this.presetTime); 
            }
        }).then(() => {
            this.sayName()
        })
    }
    sayName() {
        console.log(`Hi! This is ${this.name}`)
        return this
    }
    sleep(time) {
        this.p = this.p.then(() => {
            return this.holdon(time)
        })
        return this
    }
    eat(food) {
        this.p = this.p.then(() => {
            console.log(`Eat, ${food}`)
        })
        return this
    }
    holdon(time) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log(`Wake up after ${time}`)
                resolve()
            }, time * 1000)
        })
    }
    sleepFirst(time) {
        this.presetTime = time
        return this
    }
}