javascript的100次提问

更新中

arguments转数组

  • arguments是一个对象,只是属性从0开始排列

1. Array.prototype.slice()

const arr = Array.prototype.slice.call(arguments)

2. Array.from()

const arr = Array.from(arguments)

3. Array.prototype.concat()

const arr = Array.prototype.concat.apply([], arguments)

4. 展开运算符

const arr = [...arguments]

中断forEach返回值

在forEach中使用return不会返回,需要在try-catch中抛出错误

try {
    [1, 2, 3].forEach(item => {
        throw new Error('return')
    })
} catch (e) {
    console.log(e)
}

判断数组包含某个值

1. Array.prototype.indexOf()

[1, 2, 3].indexOf(1) > -1

2. Array.prototype.includes()

[1, 2, 3].includes(1)

3. Array.prototype.find()

[1, 2, 3].find(item => item === 1)

4. Array.prototype.findIndex()

返回的是下标

[1, 2, 3].findIndex(item => item > 1)

数组扁平化

const target = [1, [2, 3], [4, [5, 6, 7, [8]]

1. flat(ES6)

const arr = target.flat(Infinity)

2. replace + split

const arr = JSON.stringify(target).replace(/(\[|\]/g, '').split(',')

3. 递归

let res = []
const fn = function(arr) {
    arr.forEach(item => {
        Array.isArray(item) ? arguments.callee(item) : (res.push(item))
    })
}

4. reduce

const fn = function(arr) {
    return arr.reduce((pre, cur) => {
        return pre.concat(Array.isArray(cur) ? arguments.callee(cur) : cur)
    }, [])
}

5. 展开运算符

while(target.some(Array.isArray) {
    target = [].concat(...target)
}

this指向

总的来说个人觉得是谁调用就指向谁,并不是定义的时候决定的

1. 全局上下文

全局默认指向window,严格模式下默认指向undefined

fn() // 相当于 window.fn()

2. 直接调用

const obj = {
    fn: function () {}
}
const a = obj.fn
a() // 相当于全局上下文,this指向window

3. 对象.方法调用

const obj = {
    fn: function () {}
}
obj.fn() // 满足谁调用就指向谁,this是指向obj的

4. DOM事件绑定

onxxx 和 addEventListener中,this指向的是被绑定的元素

5. new XXX()

new 中,this永远指向实例,不可更改

6. 箭头函数

箭头函数没有this,指向最近的非箭头函数的this

浅拷贝

我们都知道对象其实也叫做引用类型,保存的是引用地址,两个相同引用地址对象,修改任意一个会造成相互影响;浅拷贝能对每一个值都是基本类型的数组/对象进行拷贝,但是如果某一个值的类型是对象就不能达到拷贝的效果

const arr = [1, 2, 3]

1. slice()

arr.slice()

2. concat()

[].concat(arr)

3. 展开运算符

const newArr = [...arr]
const obj = { a: 1 }
const newObj = { ...obj }

4. 手动实现

function shallowClone(target) {
    if (typeof target === 'object' && target !== null) {
        const cloneTarget = Array.isArray(target) ? [] : {}
        Object.entries(target).forEach([key, value] => {
            cloneTarget[key] = value
        })
        return cloneTarget
    } else {
        return target
    }
}

深拷贝

深拷贝能实现对对象嵌套的拷贝

1. JSON.parse(JSON.stringify(obj))

const obj = { a: 1 }
const deepClone = JSON.parse(JSON.stringify(obj))
缺点: JSON对象是为了json数据格式序列化用的,json作为js数据格式的一种简单版本,是不支持复杂的类型比如Set,Map,RegExp,Function等,并且对于循环嵌套也不能解决,毕竟是有一个转换为字符串的过程

2. 手动

const isObject = (target) => (typeof target === 'object' || typeof target === 'function') && target !== null

const deepClone =  function (target, map = new WeakMap()) {
    if (map.get(target)) {
        return target
    }
    else if (isObject(target)) {
        map.put(target, true)
        const deepTarget = Array.isArray(target) ? [] : {}
        Object.entries(target).forEach([key, value] => {
            deepTarget[key] = deepClone(value, map)
        })
        return 
    } else {
        return target
    }
} 

你可能感兴趣的:(javascript的100次提问)