回调救星

229 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情

目录

今日题

  1. 题目
  2. 分析 昨日题
  3. 题目
  4. 答案
  5. 解析 结语

今日题

题目

实现一个类 名称:CallbackSavior 属性:自定义 方法:pushrun 使用:

const cbs = new CallbackSavior();
// 向实例对象中存储一个回调函数,形参初始值为null
cbs.push(value => {
    console.log(value); // null
    return value ?? 1; // 返回给下一个可执行函数
})
// 添加一个新的回调函数,函数的第一个形参为上一个回调函数的返回值
cbs.push(value => {
    console.log(value); // 1
    return ++value;
})
// 添加一个基本数据类型,该值会直接成为下一个回调函数的形参
cbs.push("aaa");
cbs.push(value => {
    console.log(value); // aaa
    return "bbb";
})
// 添加一个Promise数据,await关键字获取到的值将成为下一个可执行函数的参数
cbs.push(new Promise(res => res("ccc")))
cbs.push(value => {
    console.log(value); // ccc
    return "ddd";
})
// run为异步函数,作用是运行存储起来的数据,返回一个Promise,成功状态下(then方法的第一个回调函数)的参数为最后一个可执行函数的返回值
cbs.run().then(value => {
    console.log(value); // ddd
});

分析

本题涵盖知识点:实例对象Promise回调函数async(异步函数的实现)……

push方法可向实例对象中存储所有类型的数据,传进来的数据会被当作下一个可执行函数的第一个形参,除了FunctionPromise类型的数据,这两种数据类型会获取返回值作为下一个可执行函数的形参

run方法按照从前往后的顺序依次获取实例对象中存储的数据作为下一个可执行函数的参数,如果遇到FunctionPromise则获取其返回值作为下一个可执行函数的参数,还有!run函数执行结束后,实例对象中存储数据的地方应被清空

注意:run是一个异步函数,目的是为了可以正常获取Promise数据类型的值

昨日题

题目

写出以下函数的执行结果,输出以单个空格分隔

function Fun() {
    say = function() {
        console.log(1)
    }
    return this
}
​
Fun.say = function () {
    console.log(2)
}
​
​
function say() {
    console.log(3)
}
​
var say = function() {
    console.log(4)
}
​
Fun.prototype.say = function () {
    console.log(5)
}
​
Fun.say()
say()
Fun().say()
new Fun.say()
new Fun().say()
say()

答案

2 4 1 2 5 1

解析

在解析答案之前我们先来看一下上面代码JS声明提升后的样子

function Fun() {
    say = function() {
        console.log(1)
    }
    return this // window
}
​
function say() {
    console.log(3)
}
​
var say;
​
Fun.say = function () {
    console.log(2)
}
​
say = function() {
    console.log(4)
}
​
Fun.prototype.say = function () {
    console.log(5)
}

第一个Fun.say():使用Fun对象下面的say()方法

Fun.say = function () {
    console.log(2)
}

第二个say():使用say()函数,在JS变量提升后的代码我们可以看到是先声明function say() {}函数,但是后面同名称的变量say被赋予了新的值function() { console.log(4) },所以在结尾调用该方法的时候调用的是变量say

var say = function() {
    console.log(4)
}

第三个Fun().say():使用Fun()函数返回的对象中的say()方法,在Fun()函数中又重新对最近的say名称变量进行了重新赋值,还有Fun()函数是用function关键字声明的,所以this指向它的调用者,也就是全局对象window,进而这部分可演化为修改全局变量sayfunction() { console.log(1) }后使用say变量

function Fun() {
    say = function() {
        console.log(1)
    }
    return this
}

第四个new Fun.say():执行了一次Fun对象下面的say()方法,并返回对应的实例对象,但是该方法中没有对this做出什么修改,所以返回了一个空的实例对象

Fun.say = function () {
    console.log(2)
}

第五个new Fun().say():对Fun()函数执行了一次new的操作,在返回的实例对象中又调用了say方法,在返回的实例对象中并没有say方法,因为this上没有绑定say方法,所以到它的构造函数Fun()下面的prototype对象上面去找,最后找到了function () { console.log(5) };

Fun.prototype.say = function () {
    console.log(5)
}

最后一个say():因为最后跟say有接触的是Fun()方法里面,所以调用的是修改的后的函数

say = function() {
    console.log(1)
}

结语

此文章已收录至《JavaScript每日一题》专栏,如果你对本专栏有任何建议,欢迎反馈。如果你对此文章中的题目还有不懂的地方,那么请在评论区留言与大家一起讨论吧。 创作不易,少年,就请留个赞再走吧!