javascript代码阅读题一

本文是一组JavaScript代码阅读题目解析,涉及IIFE、变量提升、对象属性、异步执行和Promise。第一题讨论了IIFE及其作用域,第二题解释了JavaScript的变量提升,第三题分析了对象属性的字符串键,第四题阐述了异步执行和事件循环机制,第五题介绍了Promise的执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

javascript代码阅读题

第一题

var f = function () {
    var c = 'ccc'
    return {
        a: function () {
            return c
        },
        b: function (d) {
            c = d
        }
    }
}()

console.log(f.a())  //ccc
console.warn(f.c)  //undefined
console.warn(f.b('www'))   //undefined
console.warn(f.a())		//www

输出分析:

题中 f 是一个立即执行函数表达式(IIFE)。返回一个对象,其中包含两个方法 ab 。f 中还有一个局部变量 c

  1. 在第一次调用 console.log(f.a()) 中,a 方法被调用并返回 c 的值 'ccc'。因此,它会输出 'ccc'
  2. 在第二次调用 console.warn(f.c) 中,由于 c 是在 f 的作用域内定义的局部变量,而不是作为对象的属性,因此无法通过 f.c 来访问它。因此,它会输出 undefined
  3. 在第三次调用 console.warn(f.b('www')) 中,b 方法被调用,并将局部变量 c 的值更新为 'www'。但是,b 方法没有返回值,所以输出结果为 undefined
  4. 最后一次调用 console.warn(f.a()) 中,再次调用 a 方法并返回 c 的值。由于在前一步中已经将 c 的值更新为 'www',因此它会输出 'www'

第二题

var a = 1;
(function () {
    console.log(a);
    var a = 2;
    console.log(a);
})()

输出分析

在这个代码片段中,我们定义了一个全局变量 a 并赋值为 1。然后我们创建了一个立即执行函数,并在函数内部打印变量 a 的值,接着声明一个新的局部变量 a 并赋值为 2,并再次打印变量 a 的值。

  1. 由于 JavaScript 的变量提升机制,函数内部的变量声明会被提升到函数的顶部,在使用之前已经被分配了内存空间,但还没有被赋值。所以,第一个console.log(a)会输出 undefined
  2. 接着变量a被赋值2,所以,第二个console.log(a)会输出 2

上述代码相当于以下代码:

var a = 1;
(function () {
    var a; // 声明一个局部变量 a
    console.log(a); // 输出 undefined
    a = 2; // 变量赋值
    console.log(a); // 输出 2
})();

第三题

var a = {}
var b = {key: 'a'}
var c = {key: 'c'}
a[b] = '123'
a[c] = '456'
console.log(a[b])  //456

输出分析

在这个代码片段中,我们定义了一个空对象 a,一个具有属性 key 值为 'a' 的对象 b,和一个具有属性 key 值为 'c' 的对象 c

接着,我们使用对象 b 作为属性键,给对象 a 赋值为 '123'。然后,我们又使用对象 c 作为属性键,给对象 a 赋值为 '456'

首先,我们尝试输出 a[b] 的值。根据 JavaScript 的对象属性访问规则,对象的属性键实际上是以字符串形式存储的,而不论属性键是什么类型都会被强制类型转换。因此,当我们使用对象 b 作为属性键时,它会被转换为字符串 '[object Object]'。同样地,当我们使用对象 c 作为属性键时,它也会被转换为字符串 '[object Object]'

  1. 所以,a[b] 实际上相当于 a['[object Object]'],而我们之前给 a 赋值的最后一次操作是 a[c] = '456'。因此,最终输出的结果是 '456'

第四题

console.log('script start')
async function async1() {
    await async2()
    console.log('async1 end')
}
async function async2() {
    console.log('async2 end')
}
async1()
setTimeout(function () {
    console.log('setTimeout')
}, 0)
new Promise(resolve => {
    console.log('Promise')
    resolve()
})
    .then(function () {
        console.log('promise1')
    })
    .then(function () {
        console.log('promise2')
    })
console.log('script end')

输出分析

这题考了 JavaScript 中的异步执行和事件循环机制。

  1. 首先,代码从顶部开始执行,打印出 'script start'
  2. 接着,调用了 async1() 函数,它是一个异步函数。在 async1() 函数内部,遇到了 await async2(),它会暂停函数的执行并等待 async2() 函数完成。然后,会打印出 'async2 end',await等待asyncs()执行结果,会阻塞下面的代码执行,并将下面那行console.log(‘async1 end’)放到微任务中。
  3. 接下来,遇到了 setTimeout,它是一个异步定时器函数,0秒后它的回调函数会放到异步队列中,作为一个宏任务
  4. 紧接着,遇到了 new Promise,它是一个异步操作,会立即执行传入的回调函数。在这里,回调函数中的代码会打印出 'Promise',然后调用 resolve() 完成 Promise。
  5. 接着,通过 .then() 方法添加了两个异步的回调函数。这些回调函数会在 Promise 状态改变为 resolved 后执行。因为前面的 Promise 已经通过调用 resolve() 改变了状态,所以这两个回调函数会被添加到微任务队列中,等待当前事件循环结束后执行。
  6. 下一步,打印出 'script end'
  7. 同步任务结束,访问异步回调队列中的微任务,依次打印 'async1 end''promise1''promise2'
  8. 再执行宏任务,输出'setTimeout'

总结执行结果为:

script start
async2 end
Promise
script end
async1 end
promise1
promise2
setTimeout

第五题

new Promise(resolve => {
	console.log('p1')
	resolve()
	console.log('p3')
}).then(() => {
	console.log('p2')
})

输出分析

首先创建了一个 Promise 对象,并传入一个执行器函数。在执行器函数内部,先打印了 'p1',然后调用了 resolve() 方法来触发 Promise 的解决态,并继续打印了 'p3'

接下来使用 .then() 方法注册了一个回调函数,在 Promise 进入解决态后,该回调函数会被添加到微任务队列中,等待当前宏任务结束后执行。

因此,代码的执行顺序如下:

  1. 打印 'p1'
  2. 调用 resolve()
  3. 打印 'p3'
  4. 当前宏任务结束,开始执行微任务队列
  5. 执行 .then() 注册的回调函数,打印 'p2'

所以最终的输出结果是:

p1
p3
p2

执行器函数是 Promise 对象的一个参数,它会在 Promise 被创建时立即执行。执行器函数接受两个参数,分别是 resolvereject,它们是由 JavaScript 引擎自动传入的两个函数。

在执行器函数中,我们可以执行异步操作,比如发送网络请求、读取文件等。当异步操作完成时,我们可以调用 resolve(value) 来将 Promise 置于解决态,并传递一个值作为解决的结果;或者调用 reject(reason) 来将 Promise 置于拒绝态,并传递一个原因(通常是一个 Error 对象)。

执行器函数的作用是初始化 Promise 的状态,并定义异步操作的逻辑。根据异步操作的结果,我们可以决定是将 Promise 解决(resolved)为成功态,还是拒绝(rejected)为失败态。这样,后续就可以通过 .then() 方法或 .catch() 方法来处理 Promise 的结果或错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值