你不可不知的JS面试题(第二期)

Jacquelyn38
• 阅读 1246

1、什么是继承?

子类可以使用父类的所有功能,并且对功能进行扩展。

  • 新增方法

  • 改用方法

(1)、ES6使用extends子类继承父类的方法。

 // 父类  
    class A{  
        constructor(name){  
            this.name= name;  
        }  
        getName () {  
            return this.name;  
        }  
    };  
    // 子类继承  
    class B extends A {  
        constructor(name){  
           super(name) //  记得用super调用父类的构造方法!  
        }  
        getName(){  
            const name = super.getName();  
            return name;  
        }  
    }  

    var b = new B('2');  
    console.log(b.getName()); //2

(2)、ES5的继承方法:

// 父类  
function P(name) {  
    this.name = name;  
}  
// 父类方法  
P.prototype.get=function(){  
    return this.name;  
}  
// 子类  
function C(name){  
    P.call(this,name);  
}  
// 封装继承。也就是C.prototype.__proto__ = P.prototype  
function I(Pfn,Cfn){  
    var prototype = Object.create(Pfn.prototype);  
    prototype.constructor = Cfn;  
    Cfn.prototype = prototype;  
}  
// 调用继承方法,并传入参数  
I(P,C);  


var c = new C('maomin');  
console.log(c.get()); // maomin  

(3)、ES3实现继承

使用ES3实现继承无非是替代了Object.create(Pfn.prototype),我们先来看下

你不可不知的JS面试题(第二期)大家知道我们封装的I方法是原理是C.prototype.__proto__ = P.prototype。但是我们不推荐这样,因为__proto__是浏览器内置的属性,并不是JS内置的,所以不推荐这样做。我们来封装一个方法来替代Object.create(Pfn.prototype)

function objectCreate (o) {  
 function P1() {}  
 P1.prototype = o;  
 return new P1();  
}  

你不可不知的JS面试题(第二期)完整代码:

 // 父类  
    function P(name) {  
        this.name = name;  
    }  
   // 父类方法  
    P.prototype.get = function () {  
        return this.name;  
    }  
 // 子类  
    function C(name) {  
        P.call(this, name);  
    }  
 // 封装object.create()  
    function objectCreate(o) {  
        function P1() {}  
        P1.prototype = o;  
        return new P1();  
    }  
    // 封装继承  
    //C.prototype.__proto__ = P.prototype;   
    function I(Pfn, Cfn) {  
        var prototype = objectCreate(Pfn.prototype);   
        prototype.constructor = Cfn;  
        Cfn.prototype = prototype;  
    }  

    // 调用继承方法,并传入参数  
    I(P, C);  

    var c = new C('maomin');  
    console.log(c.get()); // maomin

(4)、新增API

新增ES6方法 Reflect.setPrototypeOf()可以实现C.prototype.__proto__ = P.prototype

 function A(name){this.name=name}  
   A.prototype.get=function () {return this.name}  
   function B (name) {A.call(this,name)}  
   Reflect.setPrototypeOf(B.prototype,A.prototype);  
   var b = new B('maomin');  
   console.log(b.get()); //maomin

2、关于Promise,你知道什么?

(1)、Promise是什么?

Promise是异步编程的一种解决方案,同时他有很多规范,如Promise/A,Promise/B,Promise/D以及Promise/A的升级版Promise/A+,而ES6中采用了Promise/A+规范。

(2)、Promise的作用是什么?
  • 解决“回调地狱”问题

  • 解决并发请求问题

  • 解决异步编程代码执行顺序理解困难的问题

① 解决“回调地狱”问题

我们先看下面代码,看到会不会觉得太冗余了啊。如果代码多的话,很难维护。

 let count = 0;  
    setTimeout(() => {  
        count++;  
        console.log(`地狱${count}层`);  
        setTimeout(() => {  
            count++;  
            console.log(`地狱${count}层`);  
            setTimeout(() => {  
                 count++;  
                 console.log(`地狱${count}层`);  
            }, 500);  
        }, 500);  
    }, 500);

我们可以看到使用Promise让它永远在第一层,打印出 我还在人间 ,而不会越来越深。

 let count = 0;  
    new Promise(resolve =>{  
        setTimeout(() => {  
             count++;  
             resolve();  
        }, 500);  
    }).then(()=>{  
        return new Promise(resolve=>{  
            setTimeout(() => {  
                 count++;  
                 resolve();  
            }, 500);  
        })  
    }).then(()=>{  
        console.log('我还在人间')  
    })

② 解决并发请求问题可以在执行result1result2 结束后再执行下面的代码

const result1 = fetch('/getName');  
const result2 = fetch('/getAge');  
Promise.all([result1,result2]).then(()=>{  
// 执行  
})  

③解决异步编程代码执行顺序理解困难的问题我们先看下这个场景,get方法是异步的方法,在执行getInfo方法时,并不会先执行get方法,而是先打印出我是getInfo方法

function get() {  
    setTimeout(() => {  
        console.log('执行get方法');  
    }, 1000);  
}  
function getInfo() {  
    get();  
    console.log('我是getInfo方法');  
}  
getInfo();  
// 我是getInfo方法  
// 执行get方法  

那么,我们使用Promise来解决异步,同时我们使用了ES6asyncawait来等待get方法执行完再执行下面的代码。

function get() {  
    return new Promise((resolve)=>{  
        setTimeout(() => {  
            console.log('执行get方法');  
            resolve();  
        }, 1000);  
    })  
}  
async function getInfo() {  
    await get();  
    console.log('我是getInfo方法');  
}  
getInfo();  
// 执行get方法  
// 我是getInfo方法  

3、如何实现Promise?

我们先来了解Promise

  • Promise包含then方法

  • then方法的两个参数resolvereject

  • Promise包含3个状态:pending(等待态)resolved(成功态)rejected(失败态)

返回成功resolve:

new Promise((resolve,reject)=>{  
    setTimeout(() => {  
        resolve('success!') //返回成功状态  
    }, 1000);  
}).then((v)=>{  
    console.log(v);  
},(e)=>{  
    console.log(e);  
})  

返回错误reject:

new Promise((resolve,reject)=>{  
    setTimeout(() => {  
        reject('error!') //返回失败状态  
    }, 1000);  
}).then((v)=>{  
    console.log(v);  
},(e)=>{  
    console.log(e);  
})  

好了,我们来实现一下,封装一个Promise

 function myPromise(fn) {  
        this.status = 'pending'; // 初始化等待状态  
        this.data = undefined; // 初始化一个存储变量  
        this.resolvedCallback = []; //成功方法保存  
        this.rejectedCallback = []; // 失败方法保存  

        const resolve = (val) => {  
            if (this.status === 'pending') {  
                this.status = 'resolved';  
                this.data = val;  
                this.resolvedCallback.forEach(fu => fu.call(this));  
            }  
        }  

        const reject = (val) => {  
            if (this.status === 'pending') {  
                this.status = 'rejected';  
                this.data = val;  
                this.rejectedCallback.forEach(fu => fu.call(this));  
            }  
        }  

        fn(resolve, reject);  
    }  
    // 封装then方法  
    myPromise.prototype.then = function (onResolved, onRejected) {  
        return new myPromise((resolve, reject) => {  

            const resolvedCallback = () => {  
                const result = onResolved(this.data);  
                if (result instanceof myPromise) {  
                    result.then(resolve, reject);  
                } else {  
                    resolve(result);  
                }  
            }  
            const rejectedCallback = () => {  
                const result = onRejected(this.data);  
                if (result instanceof myPromise) {  
                    result.then(resolve, reject);  
                } else {  
                    resolve(result);  
                }  
            }  

            if (this.status === 'resolved') {  
                resolvedCallback();  
            } else if (this.status === 'rejected') {  
                rejectedCallback();  
            } else { // this.status === 'pending'  
                this.resolvedCallback.push(resolvedCallback);  
                this.rejectedCallback.push(rejectedCallback);  
            }  

        })  

    }  
    // 使用  
    new myPromise((resolve, reject) => {  
        setTimeout(() => {  
            resolve('success!');  
        }, 1000);  
    }).then((v) => {  
        console.log(v)  
    }, (e) => {  
        console.log(e)  
    }).then(() => {  
        console.log('1')  
    })

下一期更新 请关注 第三期


作者:Vam的金豆之路

主要领域:前端开发

我的微信:maomin9761

微信公众号:前端历劫之路

你不可不知的JS面试题(第二期)


本文转转自微信公众号前端历劫之路原创https://mp.weixin.qq.com/s/0vHHCviZSQfaJRX7mZkqNQ,如有侵权,请联系删除。

点赞
收藏
评论区
推荐文章
秃头王路飞 秃头王路飞
5个月前
webpack5手撸vue2脚手架
webpack5手撸vue相信工作个12年的小伙伴们在面试的时候多多少少怕被问到关于webpack方面的知识,本菜鸟最近闲来无事,就尝试了手撸了下vue2的脚手架,第一次发帖实在是没有经验,望海涵。languageJavaScript"name":"vuecliversion2","version":"1.0.0","desc
blmius blmius
1年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
光头强的博客 光头强的博客
5个月前
Java面向对象试题
1、请创建一个Animal动物类,要求有方法eat()方法,方法输出一条语句“吃东西”。创建一个接口A,接口里有一个抽象方法fly()。创建一个Bird类继承Animal类并实现接口A里的方法输出一条有语句“鸟儿飞翔”,重写eat()方法输出一条语句“鸟儿吃虫”。在Test类中向上转型创建b对象,调用eat方法。然后向下转型调用eat()方
刚刚好 刚刚好
5个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
小森森 小森森
5个月前
校园表白墙微信小程序V1.0 SayLove -基于微信云开发-一键快速搭建,开箱即用
后续会继续更新,敬请期待2.0全新版本欢迎添加左边的微信一起探讨!项目地址:(https://www.aliyun.com/activity/daily/bestoffer?userCodesskuuw5n)\2.Bug修复更新日历2.情侣脸功能大家不要使用了,现在阿里云的接口已经要收费了(土豪请随意),\\和注意
晴空闲云 晴空闲云
5个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
5个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
密钥管理系统-为你的天翼云资产上把“锁
本文关键词:数据安全,密码机,密钥管理一、你的云上资产真的安全么?1.2021年1月,巴西的一个数据库30TB数据被破坏,泄露的数据包含有1.04亿辆汽车和约4000万家公司的详细信息,受影响的人员数量可能有2.2亿;2.2021年2月,广受欢迎的音频聊天室应用Clubhouse的用户数据被恶意黑客或间谍窃取。据悉,一位身份不明的用户能够将Clubho
NVIDIA安培架构下MIG技术分析
关键词:NVIDIA、MIG、安培一什么是MIG2020年5月,NVIDIA发布了最新的GPU架构:安培,以及基于安培架构的最新的GPU:A100。安培提供了许多新的特性,MIG是其中一项非常重要的新特性。MIG的全名是MultiInstanceGPU。NVIDIA安培架构中的MIG模式可以在A100GPU上并行运行七个作业。多实
helloworld_28799839 helloworld_28799839
5个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue