Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >前端高频手写面试题整理汇总

前端高频手写面试题整理汇总

作者头像
用户1272076
发布于 2021-09-08 08:00:48
发布于 2021-09-08 08:00:48
50500
代码可运行
举报
文章被收录于专栏:张培跃张培跃
运行总次数:0
代码可运行

1、call实现原理

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Function.prototype.mycall = function (context) {
    // 当context为null时,其值则为window
    context = context || window;
    // this为调用mycall的函数。将this赋值给context的fn属性
    context.fn = this;
    // 将arguments转为数组,并从下标1位置开始截取
    let arg = [...arguments].slice(1);
    // 将arg数组的元素作为fn方法的参数执行,结果赋值给result
    let result = context.fn(...arg);
    // 删除fn属性
    delete context.fn;
    // 返回结果
    return result;
}

测试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function add(c, d){
    return this.a + this.b + c + d;
}
var obj = {a:1, b:2};
console.log(add.mycall(obj, 3, 4)); // 10

2、apply实现原理

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Function.prototype.myapply = function (context) {
    // 当context为null时,其值则为window
    context = context || window
    // this为调用myapply的函数。将this赋值给context的fn属性
    context.fn = this;
    // 如果未传值,则为一空数组
    let arg = arguments[1] || [];
    // 将arg数组的元素作为fn方法的参数执行,结果赋值给result
    let result = context.fn(...arg);
    // 删除fn属性
    delete context.fn
    // 返回结果
    return result
}

测试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function add(c, d){
    return this.a + this.b + c + d;
}
var obj = {a:1, b:2};
console.log(add.myapply(obj, [5, 6])); // 14

3、bind实现原理

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Function.prototype.mybind = function (context) {
    // this为调用mybind的函数。将this赋值给变量_this
    let _this = this;
    // 将arguments转为数组,并从下标1位置开如截取
    let arg = [...arguments].slice(1);
    // 返回函数fn
    return function fn(){
        // 通过apply方法调用函数并返回结果。
        return _this.apply(context, arg.concat(...arguments));
    }
}

测试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var obj = {
    siteName: "zhangpeiyue.com"
}
function printSiteName() {
    console.log(this.siteName);
}
var site = printSiteName.mybind(obj);
// 返回的是一个函数
console.log(site) // function () { … }
// 通过mybind使其this发生了变化
site();// zhangpeiyue.com

4、递归拷贝

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function deepClone(obj) {
    // 判断是否数组或对象,确定初始值
    let copy = obj instanceof Array ? [] : {}
    for (let i in obj) {
        if (obj.hasOwnProperty(i)) {
            copy[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
        }
    }
    return copy
}

测试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const obj = {
    siteName:"张培跃",
    info:{
        age:18,
        props:["阳光","帅气"]
    }
}
const copy1 = deepClone(obj);
console.log(copy1 === obj);// false
console.log(copy1.info === obj.info);// false
console.log(copy1.info.props === obj.info.props);// false
console.log(copy1.siteName);// 张培跃

5、setTimeout模拟setInterval

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 可避免setInterval因执行时间导致的间隔执行时间不一致
setTimeout (function () {
  // do something
  setTimeout (arguments.callee, 500)
}, 500)

6、手写new

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function myNew (fun) {
    return function () {
        // 创建一个新对象且将其隐式原型指向构造函数原型
        let obj = {
            __proto__ : fun.prototype
        }
        // 执行构造函数
        fun.call(obj, ...arguments);
        // 返回该对象
        return obj;
    }
}

测试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function Site(siteName, siteUrl) {
    this.siteName = siteName;
    this.siteUrl = siteUrl;
}
let obj = myNew(Site)("张培跃","http://www.zhangpeiyue.com");
// { siteName: '张培跃', siteUrl: 'http://www.zhangpeiyue.com' }
console.log(obj);

7、JS如何获得URL地址中的参数及值

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function query(sHref = window.location.href){
    var obj = {};
    var args = sHref.split('?');
    if(args[0] == sHref) return obj;
    var arr = args[1].split('&');
    for(var i = 0;i< arr.length;i++){
        var arg = arr[i].split('=');
        obj[arg[0]] = arg[1];
    }
    return obj;
}

测试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 倘若你当前的地址是:http://zhangpeiyue.com/s?a=1&b=2
var result = query();
console.log(result);// { a: '1', b: '2' }

// 当然你也可以指定地址:
var result = query("http://zhangpeiyue.com/s?c=3&d=4");
console.log(result);// { c: '3', d: '4' }

8、手写instanceof

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function instance_of(L,R){
    L = L.__proto__;
    R = R.prototype;
    while (true){
        if(L === null) return false;
        if(L === R) return true;
        L = L.__proto__;
    }
}

测试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function Box(){
}
var obj = new Box();
console.log(instance_of(obj,Box));// true
console.log(instance_of(obj,Function));// false
console.log(instance_of(obj,Object));// true

9、手写promise

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(function (window) {
    const PENDING = "pending";
    const FULFILLED = "fulfilled";
    const REJECTED = "rejected";
    class Promise{
        constructor() {
            // 状态,初始值为pending
            this.state = PENDING;
            // 状态值,初始值为undefined
            this.result = undefined;
            this.callbackArr = [];
            // 将当前的状态更改为成功fulfilled,值更改为value
            function _resolve(value){
                // console.log("我是最后输出的")
                // 如果状态已经更改了,那么直接返回
                if(this.state !== PENDING) return;
                this.state = FULFILLED;
                this.result = value;
                this.callbackArr.forEach(item=>{
                    item.onResolved();
                })
            }
            //将当前的状态更改为成功rejected,值更改为value
            function _reject(value){
                // 如果状态已经更改了,那么直接返回
                if(this.state !== PENDING) return;
                this.state = REJECTED;
                this.result = value;
                this.callbackArr.forEach(item=>{
                    item.onRejected();
                })
            }
            try{
                executor(_resolve.bind(this),_reject.bind(this));
            }catch (e) {
                // 发生异常之后,需要将状态更改为失败,值更改为e
                _reject.call(this,e);
            }
        }
        then(onResolved,onRejected) {
            if(!(onRejected instanceof Function)){
                // console.log("不是函数",onRejected)
                onRejected = reason => {
                    throw reason;
                }
            }
            // 1、返回了一个Promise实例。
            return new Promise((resolve,reject)=>{
                function _common(cb) {
                    setTimeout(()=>{
                        try{
                            const value = cb(this.result);
                            // 如果value是Promise,那么返回的Promise的状态,值与value相同
                            if(value instanceof Promise){
                                // 将上面注释代码简化:
                                value.then(resolve,reject);
                            }else{
                                // 不是promise,将返回的Promise的状态更改为成功,值为value
                                resolve(value);
                            }
                        }catch (e) {
                            reject(e);
                        }
                    })
                }
                if(this.state === FULFILLED){
                    _common.call(this,onResolved);
                }
                else if(this.state === REJECTED){
                    _common.call(this,onRejected);
                }else{

                    this.callbackArr.push({
                        // 当状态成功执行onResolved
                        onResolved:_common.bind(this,onResolved),
                        // 当状态失败执行onRejected
                        onRejected:_common.bind(this,onRejected)
                    })
                }
                // console.log("then",this.state);
            })
        }
        catch(onRejected) {
            this.then(undefined,onRejected);
        }
        static resolve = function (value) {
            if(value instanceof Promise){
                return value;
            }else{
                // 不是promise, 返回一个成功状态的promise
                return new Promise(function (resolve) {
                    resolve(value);
                })
            }
        }
        static reject = function (value) {
            return new Promise(function (resolve,reject) {
                reject(value);
            })
        }
        static all = function (arr) {
            const result = new Array(arr.length);
            let i = 0;
            return new Promise(function (resolve,reject) {
                arr.forEach((item,index)=>{
                    item.then(value=>{
                        result[index] = value;
                        i++;
                        if(i===arr.length){
                            resolve(result);
                        }
                    },reason=>{
                        reject(reason);
                    })
                })
            })
        }
        static race = function (arr) {
            return new Promise(function (resolve,reject) {
                arr.forEach(item=>{
                    item.then(value=>{
                        resolve(value);
                    },reason=>{
                        reject(reason);
                    })
                })
            })
        }
    }
    window.Promise = Promise;
})(window)

10、最后出道易错面试题

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 输出结果是?
function fn1() {
  console.log(1);
}
function fn2() {
  console.log(2);
}
fn1.call(fn2);
fn1.call.call(fn2);
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-08-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 张培跃 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
前端一面经典手写面试题(边面边更)
题目描述:有一组版本号如下 ['0.1.1', '2.3.3', '0.302.1', '4.2', '4.3.5', '4.3.4.5']。现在需要对其进行排序,排序的结果为 ['4.3.5','4.3.4.5','2.3.3','0.302.1','0.1.1']
helloworld1024
2022/12/20
4920
前端手写面试题合集
AJAX是 Asynchronous JavaScript and XML 的缩写,指的是通过 JavaScript 的 异步通信,从服务器获取 XML 文档从中提取数据,再更新当前网页的对应部分,而不用刷新整个网页。
helloworld1024
2022/12/14
5690
滴滴前端高频面试题
O.length >>> 0 是什么操作?就是无符号右移 0 位,那有什么意义嘛?就是为了保证转换后的值为正整数。其实底层做了 2 层转换,第一是非 number 转成 number 类型,第二是将 number 转成 Uint32 类型
gogo2027
2022/09/13
1.3K0
腾讯前端高频手写面试题
函数柯里化概念: 柯里化(Currying)是把接受多个参数的函数转变为接受一个单一参数的函数,并且返回接受余下的参数且返回结果的新函数的技术。
helloworld1024
2022/11/15
6050
经典的面试题(一)
经典的单例模式 function proxy(func) { let instance let handler = { construct(target, args) { if (!instance) { instance = Reflect.construct(func, args) } return instance } } return new Proxy(func, handler) } instanceof con
前端老鸟
2019/08/05
3450
经典的面试题(一)
滴滴前端一面高频手写面试题汇总_2023-02-28
浅拷贝是指,一个新的对象对原始对象的属性值进行精确地拷贝,如果拷贝的是基本数据类型,拷贝的就是基本数据类型的值,如果是引用数据类型,拷贝的就是内存地址。如果其中一个对象的引用内存地址发生改变,另一个对象也会发生变化。
用户10358576
2023/02/28
7690
前端一面高频面试题(附答案)
我们常说的代理也就是指正向代理,正向代理的过程,它隐藏了真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替来请求。
loveX001
2022/12/14
6390
社招前端经典手写面试题合集
使用时间戳的节流函数会在第一次触发事件时立即执行,以后每过 wait 秒之后才执行一次,并且最后一次触发事件不会被执行
helloworld1024
2022/10/19
7910
高级前端必会手写面试题及答案1
下面来看一道比较典型的问题,通过这个问题来对比几种异步编程方法:红灯 3s 亮一次,绿灯 1s 亮一次,黄灯 2s 亮一次;如何让三个灯不断交替重复亮灯?
helloworld1024
2023/01/02
9480
字节前端高频手写面试题(持续更新中)1
观察者需要放到被观察者中,被观察者的状态变化需要通知观察者 我变化了 内部也是基于发布订阅模式,收集观察者,状态变化后要主动通知观察者
helloworld1024
2023/01/03
7200
js手写面试题总结
使用时间戳的节流函数会在第一次触发事件时立即执行,以后每过 wait 秒之后才执行一次,并且最后一次触发事件不会被执行
helloworld1024
2022/12/16
6410
前端二面手写面试题总结
then 方法返回一个新的 promise 实例,为了在 promise 状态发生变化时(resolve / reject 被调用时)再执行 then 里的函数,我们使用一个 callbacks 数组先把传给then的函数暂存起来,等状态改变时再调用。
helloworld1024
2022/10/27
8560
百度前端二面常见面试题合集
这里可以理解为await后面的语句相当于放到了new Promise中,下一行及之后的语句相当于放在Promise.then中。
bb_xiaxia1998
2022/09/12
5850
JavaScript面试题
1、实现一个call函数 // 思路:将要改变this指向的方法挂到目标this上执行并返回 Function.prototype.mycall = function (context) { if (typeof this !== 'function') { throw new TypeError('not funciton') } context = context || window context.fn = this let arg = [...arguments].sl
挨踢小子部落阁
2019/08/13
6120
对JS原理很无奈?送给被原理题打蒙圈的面试者!(一)
instanceof 来判断对象的具体类型,当然, instanceof 也可以判断一个实例是否是其父类型或者祖先类型的实例。先来看几个示例:
用户1272076
2019/07/30
7040
腾讯前端二面面试题(附答案)
什么是偏函数?偏函数就是将一个 n 参的函数转换成固定 x 参的函数,剩余参数(n - x)将在下次调用全部传入。举个例子:
beifeng1996
2022/09/13
1.2K0
2022必会的前端面试手写题
instanceof 运算符用于判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。
buchila11
2022/07/29
5880
高级前端手写面试题汇总
可以给img标签统一自定义属性data-src='default.png',当检测到图片出现在窗口之后再补充src属性,此时才会进行图片资源加载。
helloworld1024
2022/12/15
8700
前端二面手写面试题总结3
event bus既是node中各个模块的基石,又是前端组件通信的依赖手段之一,同时涉及了订阅-发布设计模式,是非常重要的基础。
helloworld1024
2023/01/05
8070
美团前端一面必会手写面试题汇总
输入字符串s,以及其重复的次数,输出重复的结果,例如输入abc,2,输出abcabc。
helloworld1024
2022/10/29
5190
相关推荐
前端一面经典手写面试题(边面边更)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验