前端手写面试题(包含答案解析)持续更新中~

写的不好,如有问题的地方忘大家提出,互相学习,谢谢

数据去重的方法

let arr = [1, 3, 5, 7, 9, 2, 6, 1, 7, 9]
/*
    使用indexOf方法
    indexOf:在数组中查找某个元素,找到返回对应的下标,否则返回 -1 (在等于-1也就是未查找到元素的时候把该元素添加到新数组中去)
*/
function repeat(arr) {
    
    
    var newArr = []
    for (var i = 0; i < arr.length; i++) {
    
    
        if (newArr.indexOf(arr[i]) === -1) {
    
    
            newArr.push(arr[i])
        }
    }
    return newArr
}

/*
    使用ES6中的 Set() 方法
*/
function repeat(arr) {
    
    
    return Array.from(new Set(arr));
}

/*
    使用数组原型对象上的 forEach 和 includes方法
*/
function repeat(arr) {
    
    
    let newArr = [];
    arr.forEach(item => {
    
    
        return newArr.includes(item) ? '' : newArr.push(item);
    });
    return newArr;
}

/*
    使用数组原型对象上的includes方法
*/
function repeat(arr) {
    
    
    var newArr = []
    for (var i = 0; i < arr.length; i++) {
    
    
        if (!newArr.includes(arr[i])) {
    
    
            newArr.push(arr[i])
        }
    }
    return newArr;
}

/*
    使用对象属性的特性,没有该属性的时候存入新数组
*/
function repeat(arr) {
    
    
    var obj = {
    
    }
    var newArr = []
    for (let i = 0; i < arr.length; i++) {
    
    
        if (!obj[arr[i]]) {
    
    
            obj[arr[i]] = 1
            newArr.push(arr[i])
        }
    }
    return newArr;
}
console.log(repeat(arr))

防抖

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <input type="button" value="防抖按钮">
</body>

</html>
<script>
    const button = document.querySelector('input')

    function antiShake() {
      
      
        console.log('防抖')
    }

    function debounce(func, delay) {
      
      
        let timer // 多个函数共用外部变量
        return function () {
      
      
            let _this = this // 在使用防抖函数时antiShake() this会指向window 在这里使用apply改变this指向input
            let args = arguments // 增加参数
            clearTimeout(timer)
            timer = setTimeout(function () {
      
      
                func.apply(_this, args)
            }, delay)
        }
    }

    button.addEventListener('click', debounce(antiShake, 2000))
</script>

节流

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    节流:<input type="text">
</body>

</html>
<script>
    const input = document.querySelector('input')

    function getInputContent() {
      
      
        console.log('当前输入的值:', input.value)
    }

    function throttle(func, delay) {
      
      
        let timer
        return function () {
      
      
            let _this = this // 在使用防抖函数时antiShake() this会指向window 在这里使用apply改变this指向input
            let args = arguments // 增加参数
            if (timer) {
      
       // 如果timer为true也就是被赋值了(直接返回不执行任务)
                return
            }
            // timer为false也就是没有被赋值或者任务已经结束了,那么就为timer赋值进行延迟执行,延迟执行以后清空timer的值,可以不使用clearTimeout直接清空timer的值就行了
            timer = setTimeout(function () {
      
      
                func.apply(_this, args)
                timer = null
            }, delay)
        }
    }

    input.addEventListener('input', throttle(getInputContent, 2000))
</script>

冒泡排序

const arr = [122, 421, 32, 521, 3, 984, 53, 874]

function bubblingSort(arr) {
    
    
    let temp;
    for (let i = 0; i < arr.length - 1; i++) {
    
     // 确定循环的次数(重要的作用就是下一轮不会重复对比最后一个元素)
        for (let j = 0; j < arr.length - 1 - i; j++) {
    
    
            if (arr[j] > arr[j + 1]) {
    
    
                temp = arr[j]
                arr[j] = arr[j + 1]
                arr[j + 1] = temp
            }
        }
    }
    return arr;
}

console.log(bubblingSort(arr))

二分查找数组下标

// 需要先将数组排序
const arr = [3, 32, 64, 88, 110, 143, 164, 185, 230, 289]

function searching(target) {
    
    
    var start = 0, end = arr.length - 1, middle, element;
    while (start <= end) {
    
    
        middle = Math.floor((start + end) / 2)
        element = arr[middle]
        if (element === target) {
    
    
            return middle
        } else if (target < element) {
    
    
            end = middle - 1
        } else {
    
    
            start = middle + 1
        }
    } return -1
}

console.log(searching(185))

二分数组排序

const arr = [110, 289, 3, 32, 64, 164, 88, 143, 185, 230]

function binarySorting(arr) {
    
    
    if (arr.length == 0) {
    
    
        return [];
    }
    var middle = Math.floor(arr.length / 2);
    var c = arr.splice(middle, 1);
    var left = [];
    var right = [];

    for (var i = 0; i < arr.length; i++) {
    
    
        arr[i] < c ? left.push(arr[i]) : right.push(arr[i]);
    }

    return binarySorting(left).concat(c, binarySorting(right));
}

console.log(binarySorting(arr));

了解Promise

const isEmpower = true

const promise = new Promise((resolve, reject) => {
    
    
    if (isEmpower) {
    
    
        resolve('成功授权了') // 返回成功结果
    } else {
    
    
        reject('授权失败了') // 返回失败结果
    }
})

promise.then(res => {
    
    
    console.log(res) // 成功时的回掉
}).catch(res => {
    
    
    console.log(res) // 失败时的回掉
}).finally(() => {
    
    
    console.log('最终我还是访问了') // 无论成功还是失败都会执行
})

class类

这里只是一个简单的例子
深入了解请看 深入理解Javascript中的class类

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .button_1 {
      
      
            border: none;
            width: 100px;
            height: 42px;
            border-radius: 5px;
            cursor: pointer;
            color: #fff;
            background-color: #409EFF;
        }
    </style>
</head>

<body>
    <button class="button_1">一级</button>
</body>
<script>
    // 拿到两个按钮
    const button_1 = document.querySelector('.button_1');

    // 创建 Speech class类
    class Speech {
      
      
        // 使用 constructor 初始化操作 (每次new的时候都会触发 constructor)
        constructor(name, say) {
      
      
            this.name = name;
            this.say = say;
        }
        work() {
      
      
            console.log(this.name, this.say)
        }
    }

    button_1.addEventListener('click', () => {
      
      
        const speech = new Speech('张三', '说,你是谁')
        speech.work() // 调用 speech 的 work 方法
    })
</script>

原生实现Call


// 原生实现call
// 先回顾一下call的用法

function person() {
    
    
    console.log(this.name)
}
var people = {
    
    
    name: '张三'
}

/**
 * call是从哪里来的
 * 在Javascript中每个函数其实都是Function对象
 * 而Function则是构造函数,构造函数是有原型对象的,也就是Function.prototype
 * Function.prototype中可以有很多属性可以使用,call就是从里面来的
 * 因此我们需要在原型中添加新的call属性,call是一种属性也是一种方法,可以看到上面的例子调用call的时候加了括号
 * 接下来我们为原型对象添加新的方法
*/

function person() {
    
     console.log(this.name) }
var people = {
    
     name: '张三' }

Function.prototype.newCall = function (obj) {
    
    
    console.log(this)
}

person.newCall(people); // 这个时候newCall中输出的this是person
// 函数person开始进行调用然后执行newCall然后发现了this,因此需要绑定,person是真正调用的地方,this自然绑定到person

// 接下来我们来调整代码
Function.prototype.newCall = function (obj) {
    
    
    // 为行参添加一个函数,并且吧this赋值给这个函数,然后在执行这个方法,相当于给对象添加了一个person函数,要记得讲这个函数删掉
    // 因为我们不能改写了对象,现在执行就得到和call一样的方法了
    obj.p = this
    obj.p()
    delete obj.p
}
person.newCall(people); // 输出:张三

// 到这里还没有结束,我们知道call第一个参数是this的指向,后面还可以有很多参数

function person(a, b, c, d) {
    
     // 这里的参数就是函数本身的参数了
    console.log(this.name);
    console.log(a, b, c, d); // undefined undefined undefined undefined 输出 undefined 肯定是不可行的
}
var people = {
    
     name: '张三' }
// 函数本身的参数是没有this的,我们需要吧所有的参数另外保存起来,并且不保留第一个this参数
// 要获取函数的参数需要用到arguments对象
Function.prototype.newCall = function (obj) {
    
    
    obj.p = this
    var newArguments = []
    for (var i = 1; i < arguments.length; i++) {
    
    
        newArguments.push(arguments[i])
    }
    console.log(newArguments) // 输出 ['a','b','c','d']
    obj.p()
    delete obj.p
}
person.newCall(people, 'a', 'b', 'c', 'd');

// 修改后代码 for 循环

function person(a, b, c, d) {
    
    
    console.log(this.name); // 输出:张三
    console.log(a, b, c, d); // 输出 a,b,c,d
}
var people = {
    
     name: '张三' }

Function.prototype.newCall = function (obj) {
    
    
    obj.p = this
    var newArguments = []
    for (var i = 1; i < arguments.length; i++) {
    
    
        newArguments.push('arguments[' + i + ']')
    }
    eval('obj.p(' + newArguments + ')')
    delete obj.p
}

person.newCall(people, 'a', 'b', 'c', 'd');

// 这个时候如果我们吧people传入null就会出错

Function.prototype.newCall = function (obj) {
    
    
    var obj = obj || window // 如果对象存在就不管,如果是null就指向window
    obj.p = this
    var newArguments = []
    for (var i = 1; i < arguments.length; i++) {
    
    
        newArguments.push('arguments[' + i + ']')
    }
    eval('obj.p(' + newArguments + ')')
    delete obj.p
}

person.newCall(null, 'a', 'b', 'c', 'd'); // 修改obj对象,存在就忽略不存在就指向window

// 值的返回

function person(a, b, c, d) {
    
    
    return {
    
    
        name: this.name,
        a: a, b: b, c: c, d: d
    }
}
var people = {
    
     name: '张三' }

Function.prototype.newCall = function (obj) {
    
    
    var obj = obj || window
    obj.p = this
    var newArguments = []
    for (var i = 1; i < arguments.length; i++) {
    
    
        newArguments.push('arguments[' + i + ']')
    }
    let result = eval('obj.p(' + newArguments + ')') // 保存到一个变量进行返回
    delete obj.p
    return result // 返回语句写在最后
}

var value = person.newCall(people, 'a', 'b', 'c', 'd');
console.log(value) // 输出 {name: '张三', a: 'a', b: 'b', c: 'c', d: 'd'}

原生实现apply

// 原生实现apply
// apply和call有一个重要的区别,就是参数都放在一个数组里
// 把上面实现call的思路拿过来
function person(a, b, c, d) {
    
    
    console.log(this.name); // 输出:张三
    console.log(a, b, c, d); // 输出:a,b,c,d
}
var people = {
    
     name: '张三' }

Function.prototype.newApply = function (obj, arr) {
    
    
    var obj = obj || null;
    obj.p = this
    if (!arr) {
    
     // 先判断,如果没有输入数组就直接执行
        obj.p()
    } else {
    
     // 有参数时:和刚刚实现call的方法是类似的
        var newArguments = []
        for (var i = 0; i < arr.length; i++) {
    
    // 注意初始值 i = 0  因为要数组的所有元素
            newArguments.push('arr[' + i + ']')
        }
        eval('obj.p(' + newArguments + ')')
    }
    delete obj.p
}

person.newApply(people, ['a', 'b', 'c', 'd']);

// 接下来说函数中返回对象的问题

function person(a, b, c, d) {
    
    
    return {
    
    
        name: this.name,
        a: a, b: b, c: c, d: d
    }
}
var people = {
    
     name: '张三' }

Function.prototype.newApply = function (obj, arr) {
    
    
    var obj = obj || null;
    var result; // 因为有if提前声明
    obj.p = this
    if (!arr) {
    
    
        result = obj.p()
    } else {
    
    
        var newArguments = []
        for (var i = 0; i < arr.length; i++) {
    
    
            newArguments.push('arr[' + i + ']')
        }
        result = eval('obj.p(' + newArguments + ')')
    }
    delete obj.p
    return result
}

var value = person.newApply(people, ['a', 'b', 'c', 'd']);
console.log(value) // 输出 {name: '张三', a: 'a', b: 'b', c: 'c', d: 'd'}

猜你喜欢

转载自blog.csdn.net/m0_67584973/article/details/130344204