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

Jacquelyn38
• 阅读 1666

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,如有侵权,请联系删除。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
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
ZY ZY
3年前
js继承的几种方式
1.原型链继承原型链继承:想要继承,就必须要提供父类(继承谁,提供继承的属性)//父级functionPerson(name)//给构造函数添加参数this.namename;this.age10;this.sumfunction()console.log(this.name)//原
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
Easter79 Easter79
3年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
JS必知的6种继承方式
JS作为面向对象的弱类型语言,继承也是其非常强大的特性之一。那么如何在JS中实现继承呢?让我们拭目以待JS继承的实现方式既然要实现继承,那么首先我们得有一个父类,代码如下:// 父类function Person(name) { // 给构造函数添加了参数  this.name  name;
Wesley13 Wesley13
3年前
Java的类继承
知识点1、继承作用:提高代码的重用性,继承之后子类可以继承父类中的属性和方法减少重复代码条件:子类和父类要满足isa的逻辑关系,才能使用继承。如:苹果isa水果语法:使用extends连接子类和父类。子类extends父类Java是单继承,一个类只能继承一个父类。子类不能继承父类私有的属性,但是可以
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable