22道js输出顺序问题,你能做出几道
admin
2024-01-22 05:56:13
0

前言

最近在准备面试题,console的输出顺序之前一直迷迷糊糊。

必备知识

JS是单线程的

单线程是 JavaScript 核心特征之一。这意味着,在 JS 中所有任务都需要排队执行,前一个任务结束,才会执行后一个任务。
所以这就造成了一个问题:如果前一个任务耗时很长,后一个任务就不得不一直等着前面的任务执行完才能执行。比如我们向服务器请求一段数据,由于网络问题,可能需要等待 60 秒左右才能成功返回数据,此时只能等待请求完成,JS 才能去处理后面的代码。

同步任务和异步任务

为了解决JS单线程带来的问题,JavaScript 就将所有任务分成了同步任务和异步任务。

同步任务(Synchronous)

同步任务指的是当前一个(如果有)任务执行完毕,接下来可以立即执行的任务。这些任务将在主线程上依次排队执行。也就是说排排队

//for(){} 和 console.log() 将会依次执行,最终输出 0 1 2 3 4 done。
for (let i = 0; i < 5; i++) {
console.log(i)
}
console.log('done')

异步任务(Asynchronous)

异步任务相对于同步任务,指的是不需要进入主线程排队执行,而是进入超车道、并车道。也就是任务队列中,形成一系列的任务。这些任务只有当被通知可以执行的时候,该任务才会重新进入主线程执行。

//下面的 then() 方法需要等待 Promise 被 resolve() 之后才能执行,它是一个异步任务。最终输出 1 3 2。
console.log(1)Promise.resolve().then(() => {console.log(2)
})console.log(3)

具体来说就是,所有同步任务会在主线程上依次排队执行,形成一个执行栈(Execution Context
Stack)。主线程之外,还存在一个任务队列。当异步任务有了运行结果,会在任务队列之中放置对应的事件。当执行栈中的所有同步任务执行完毕,任务队列里的异步任务就会进入执行栈,然后继续依次执行。

异步任务(任务队列)可以分为

  • macrotasks(taskQueue):宏任务 task,也是我们常说的任务队列

    • macrotasks 的划分:(注意先后顺序!)
      • (1)setTimeout(延迟调用)
      • (2)setInterval(间歇调用)
      • (3)setImmediate(Node 的立即调用)
      • (4)requestAnimationFrame(高频的 RAF)
      • (5)I/O(I/O 操作)
      • (6)UI rendering(UI 渲染)
      • (7) 包裹在一个 script 标签中的 js 代码也是一个 Macrotasks

注意: (1)每一个 macrotask 的回调函数要放在下一车的开头去执行! (2)只有 setImmediate 能够确保在下一轮事件循环立即得到处理

  • microtasks:微任务(也称 job)调度在当前脚本执行结束后,立即执行的任务,以避免付出额外一个 task 的费用。

    • microtasks :(注意先后顺序!)
      • (1)process.nextTick(Node 中 定义出一个动作,并且让这个动作在下一个事件轮询的时间点上执行)
      • (2)Promises(详情看这篇文章:www.jianshu.com/p/06d16ce41…
      • (3)Object.observe(原生观察者实现,已废弃)
      • (4)MutationObserver(监听 DOM change) 只有在 nextTick 空了才处理其它 microtask。(Next tick queue has even higher priority
        over the Other Micro tasks queue.)

一个事件循环(eventLoop)的执行顺序(非常重要):

  • ① 开始执行脚本。
  • ② 取 macrotasks(taskQueue)中的第一个 task 执行,该 task 的回调函数 放在下一个 task 开头 执行。
  • ③ 取 microtasks 中的全部 microtask 依次执行,当这些 microtask 执行结束后,可继续添加 microtask 继续执行,直到 microtask 队列为空。
  • ④ 取 macrotasks(taskQueue)中的第二个 task 执行,该 task 的回调函数 放在下一个 task 开头 执行。
  • ⑤ 再取 microtasks 中的全部 microtask 依次执行,当这些 microtask 执行结束后,可继续添加 microtask 继续执行,直到 microtask 队列为空。
  • ⑥ 循环 ② ③ 直到 macrotasks、microtasks 为空。

Promise 之所以无法使用 catch 捕获 setTimeout 回调中的错误,是因为 Promise 的 then/catch 是在 setTimeout 之前执行的。

参考 前端进阶面试题详细解答

事件循环的顺序,决定了 JavaScript 代码的执行顺序。它从 script (整体代码) 开始第一次循环。之后全局上下文进入函数调用栈。直到调用栈清空 (只剩全局),然后执行所有的 microtasks。当所有可执行的
microtasks 执行完毕之后。循环再次从 macrotasks 开始,找到其中一个任务队列执行完毕,然后再执行所有的 microtasks,这样一直循环下去。

翻译过来就是,先执行 Microtasks queue 中的所有 Microtasks,再挑一个 Macrotasks queue 来执行其中所有 Macrotasks,然后继续执行 Microtasks queue 中的所有
Microtasks,再挑一个 Macrotasks queue 来执行其中所有 Macrotasks ……

这也就解释了,为什么同一个事件循环中的 Microtasks 会比 Macrotasks 先执行。

习题1

console.log(1)
setTimeout(()=>{console.log(2)
},0)
process.nextTick(()=>{console.log(3)
})
new Promise((resolve)=>{console.log(4)resolve()
}).then(()=>{console.log(5)
})

习题1解析

第一轮事件循环

主流程Macro event queueMicro event queue
console.log(1)setTimeoutprocess
console.log(4)then
  1. 首先执行同步任务,按出现顺序,输出 1
  2. 遇到 setTimeout,放入Macro event queue
  3. 遇到 process,放入 Micro event queue
  4. 遇到 promise,先立即执行,输出 4,并将 then 回调放入 Micro event queue
  5. 然后看 Micro event queue,逐个执行,输出 3, 输出 5
  6. 第一轮 Event Loop 执行结束

第二轮事件循环

主流程Macro event queueMicro event queue
setTimeout
  1. 取出 Macro event queue 第一个放入主流程执行
  2. 输出 2
  3. Micro event queue 没有任务
  4. 第二轮 Event Loop 执行结束

习题2

console.log(1)
setTimeout(() => {console.log(2)
}, 0)
process.nextTick(() => {console.log(3)
})
new Promise((resolve) => {console.log(4)resolve()
}).then(() => {console.log(5)
})
setTimeout(() => {console.log(6)
}, 0)
new Promise((resolve) => {console.log(7)setTimeout(() => {console.log(8)resolve()}, 0)
}).then(() => {console.log(9)setTimeout(() => {console.log(10)new Promise((resolve) => {console.log(11)resolve()}).then(() => {console.log(12)})}, 0)
})
// 1, 4, 7, 3, 5, 2, 6, 8, 9, 10, 11, 12

习题2解析

第一轮事件循环

主流程Macro event queueMicro event queue
console.log(1)setTimeout2process3
console.log(4)setTimeout6then5
console.log(7)setTimeout8
  1. 主流程输出:1, 4, 7
  2. 执行第一个 Micro event queue:输出 3
  3. 第二个 Micro event queue:输出 5
  4. Micro event queue 清空,第一轮执行完毕

第二轮事件循环

主流程Macro event queueMicro event queue
setTimeout2setTimeout6
setTimeout8
  1. 主流程输出 2
  2. Micro event queue 为空,第二轮执行完毕

第三轮事件循环

主流程Macro event queueMicro event queue
setTimeout6setTimeout8
  1. 主流程输出 6
  2. 第三轮执行完毕

第四轮事件循环

主流程Macro event queueMicro event queue
setTimeout9setTimeout10then9
  1. 注意,这里执行输出 8 后,resolve,这时才向 Micro event queue 压入 then 回调
  2. 执行 then9 回调,输出 9
  3. 又有新的 setTimeout,压入 Macro event queue
  4. 这轮循环没有东西可执行,结束

第五轮事件循环

主流程Macro event queueMicro event queue
console.log(10)then12
console.log(11)
  1. 第五轮,setTimeout10 进入主流程,输出 10
  2. 遇到 promise,输出 11
  3. resolve, 压入 then 到 Micro event queue
  4. 取出 Micro event queue 执行,输出 12

习题3

// 以下代码在 Node 环境运行:process.nextTick 由 Node 提供
console.log("1")
setTimeout(function () {console.log("2")process.nextTick(function () {console.log("3")})new Promise(function (resolve) {console.log("4")resolve()}).then(function () {console.log("5")})
})process.nextTick(function () {console.log("6")
})new Promise(function (resolve) {console.log("7")resolve()
}).then(function () {console.log("8")
})setTimeout(function () {console.log("9")process.nextTick(function () {console.log("10")})new Promise(function (resolve) {console.log("11")resolve()}).then(function () {console.log("12")})
})// 最终输出:1 7 6 8 2 4 3 5 9 11 10 12

习题4

setTimeout(()=>{console.log("setTimeout1");Promise.resolve().then(data => {console.log(222);});
},0);
setTimeout(()=>{console.log("setTimeout2");
},0);
Promise.resolve().then(data=>{console.log(111);
});
//111 setTimeout1 222 setTimeout2

习题4解析

  1. 主线程上没有需要执行的代码
  2. 接着遇到setTimeout 0,它的作用是在 0ms 后将回调函数放到宏任务队列中(这个任务在下一次的事件循环中执行)。
  3. 接着遇到setTimeout 0,它的作用是在 0ms 后将回调函数放到宏任务队列中(这个任务在再下一次的事件循环中执行)。
  4. 首先检查微任务队列, 即 microtask队列,发现此队列不为空,执行第一个promise的then回调,输出 ‘111’。
  5. 此时microtask队列为空,进入下一个事件循环, 检查宏任务队列,发现有 setTimeout的回调函数,立即执行回调函数输出 ‘setTimeout1’,检查microtask
    队列,发现队列不为空,执行promise的then回调,输出’222’,microtask队列为空,进入下一个事件循环。
  6. 检查宏任务队列,发现有 setTimeout的回调函数, 立即执行回调函数输出’setTimeout2’。

习题5

console.log('script start');setTimeout(function () {console.log('setTimeout---0');
}, 0);setTimeout(function () {console.log('setTimeout---200');setTimeout(function () {console.log('inner-setTimeout---0');});Promise.resolve().then(function () {console.log('promise5');});
}, 200);Promise.resolve().then(function () {console.log('promise1');
}).then(function () {console.log('promise2');
});
Promise.resolve().then(function () {console.log('promise3');
});
console.log('script end');
/*script startscript endpromise1promise3promise2setTimeout---0setTimeout---200promise5inner-setTimeout---0*/

习题5解析

  1. 首先顺序执行完主进程上的同步任务,第一句和最后一句的console.log
  2. 接着遇到setTimeout 0,它的作用是在 0ms 后将回调函数放到宏任务队列中(这个任务在下一次的事件循环中执行)。
  3. 接着遇到setTimeout 200,它的作用是在 200ms 后将回调函数放到宏任务队列中(这个任务在再下一次的事件循环中执行)。
  4. 同步任务执行完之后,首先检查微任务队列, 即 microtask队列,发现此队列不为空,执行第一个promise的then回调,输出 ‘promise1’,然后执行第二个promise的then回调,输出’
    promise3’,由于第一个promise的.then()的返回依然是promise,所以第二个.then()会放到microtask队列继续执行,输出 ‘promise2’;
  5. 此时microtask队列为空,进入下一个事件循环, 检查宏任务队列,发现有 setTimeout的回调函数,立即执行回调函数输出 ‘setTimeout—0’,检查microtask 队列,队列为空,进入下一次事件循环.
  6. 检查宏任务队列,发现有 setTimeout的回调函数, 立即执行回调函数输出’setTimeout—200’.
  7. 接着遇到setTimeout 0,它的作用是在 0ms 后将回调函数放到宏任务队列中,检查微任务队列,即 microtask 队列,发现此队列不为空,执行promise的then回调,输出’promise5’。
  8. 此时microtask队列为空,进入下一个事件循环,检查宏任务队列,发现有 setTimeout 的回调函数,立即执行回调函数输出,输出’inner-setTimeout—0’。代码执行结束.

习题6

console.log("1");setTimeout(function cb1(){console.log("2")
}, 0);new Promise(function(resolve, reject) {console.log("3")resolve();
}).then(function cb2(){console.log("4");
})console.log("5")
// 1 3 5 4 2

习题6解析

习题7

console.log("1");setTimeout(() => {console.log("2")new Promise(resolve => {resolve()}).then(() => {console.log("3")})
}, 0);setTimeout(() => {console.log("4")
}, 0);console.log("5")
// 1 5 2 3 4 

习题7解析

习题8

console.log("1");setTimeout(() => {console.log("2")new Promise(resolve => {console.log(6)resolve()}).then(() => {console.log("3")})
}, 0);setTimeout(() => {console.log("4")
}, 0);console.log("5")
// 1 5 2 6 3 4 

习题8解析

习题9

console.log('start')
setTimeout(function(){console.log('宏任务1号')
})
Promise.resolve().then(function(){console.log('微任务0号')
})
console.log('执行栈执行中')
setTimeout(function(){console.log('宏任务2号')Promise.resolve().then(function(){console.log('微任务1号')})
},500)setTimeout(function(){console.log('宏任务3号')setTimeout(function(){console.log('宏任务4号')Promise.resolve().then(function(){console.log('微任务2号')})},500)Promise.resolve().then(function(){console.log('微任务3号')})
},600)
console.log('end')
// start 执行栈执行中 end 微任务0号 宏任务1号 宏任务2号 微任务1号 宏任务3号 微任务3号 宏任务4号 微任务2号

习题9解析

习题10

function test() {console.log(1)setTimeout(function () {  // timer1console.log(2)}, 1000)
}test();setTimeout(function () {        // timer2console.log(3)
})new Promise(function (resolve) {console.log(4)setTimeout(function () {  // timer3console.log(5)}, 100)resolve()
}).then(function () {setTimeout(function () {  // timer4console.log(6)}, 0)console.log(7)
})console.log(8)
//1 4 8 7 3 6 5 2

习题10解析

结合我们上述的JS运行机制再来看这道题就简单明了的多了

  1. JS是顺序从上而下执行
  2. 执行到test(),test方法为同步,直接执行,console.log(1)打印1
  3. test方法中setTimeout为异步宏任务,回调我们把它记做timer1放入宏任务队列
  4. 接着执行,test方法下面有一个setTimeout为异步宏任务,回调我们把它记做timer2放入宏任务队列
  5. 接着执行promise,new Promise是同步任务,直接执行,打印4
  6. new Promise里面的setTimeout是异步宏任务,回调我们记做timer3放到宏任务队列
  7. Promise.then是微任务,放到微任务队列
  8. console.log(8)是同步任务,直接执行,打印8
  9. 主线程任务执行完毕,检查微任务队列中有Promise.then
  10. 开始执行微任务,发现有setTimeout是异步宏任务,记做timer4放到宏任务队列
  11. 微任务队列中的console.log(7)是同步任务,直接执行,打印7
  12. 微任务执行完毕,第一次循环结束
  13. 检查宏任务队列,里面有timer1、timer2、timer3、timer4,四个定时器宏任务,按照定时器延迟时间得到可以执行的顺序,即Event
    Queue:timer2、timer4、timer3、timer1,依次拿出放入执行栈末尾执行 (插播一条:浏览器 event loop 的 Macrotask queue,就是宏任务队列在每次循环中只会读取一个任务)
  14. 执行timer2,console.log(3)为同步任务,直接执行,打印3
  15. 检查没有微任务,第二次Event Loop结束
  16. 执行timer4,console.log(6)为同步任务,直接执行,打印6
  17. 检查没有微任务,第三次Event Loop结束
  18. 执行timer3,console.log(5)同步任务,直接执行,打印5
  19. 检查没有微任务,第四次Event Loop结束
  20. 执行timer1,console.log(2)同步任务,直接执行,打印2
  21. 检查没有微任务,也没有宏任务,第五次Event Loop结束 结果:1,4,8,7,3,6,5,2

习题11

setTimeout(() => {console.log(1)
}, 0)new Promise((resolve, reject) => {console.log(2)resolve(3)
}).then(val => {console.log(val)
})console.log(4) 
// 2 4 3 1

习题11解析

习题12

for (let i = 0; i < 5; i++) {console.log(i)
}
console.log('done')
// 0 1 2 3 4 done

习题12解析

习题13

console.log(1)Promise.resolve().then(() => {console.log(2)
})console.log(3)
//1 3 2

习题13解析

习题14

setTimeout(() => {console.log(1)
}, 0)
for (let i = 2; i <= 3; i++) {console.log(i)
}
console.log(4)
setTimeout(() => {console.log(5)
}, 0)
for (let i = 6; i <= 7; i++) {console.log(i)
}
console.log(8)
//2 3 4 6 7 8 1 5

习题14解析

习题15

console.log(1)async function async1() {await async2()console.log(2)
}
async function async2() {console.log(3)
}
async1()setTimeout(() => {console.log(4)
}, 0)new Promise(resolve => {console.log(5)resolve()
}).then(() => {console.log(6)}).then(() => {console.log(7)})console.log(8)
// 1 3 5 8 2 6 7 4

习题15解析

习题16

console.log(1)function a() {return new Promise(resolve => {console.log(2)setTimeout(() => {console.log(3)}, 0)resolve()})
}a().then(() => {console.log(4)
})
//1 2 4 3

习题16解析

习题17

console.log('script start');setTimeout(function() {console.log('setTimeout');
}, 0);Promise.resolve().then(function() {console.log('promise1');
}).then(function() {console.log('promise2');
});console.log('script end');
//script start、script end、promise1、promise2、setTimeout

习题17解析

  1. 整体script作为第一个宏任务进入主线程,遇到console.log,输出script start

  2. 遇到 setTimeout,其回调函数被分发到宏任务 Event Queue 中

  3. 遇到 Promise,其 then函数被分到到微任务 Event Queue 中,记为 then1,之后又遇到了 then 函数,将其分到微任务 Event Queue 中,记为 then2

  4. 遇到 console.log,输出 script end。至此,Event Queue中存在三个任务,如下表:

    主流程Macro event queueMicro event queue
    console.log(‘script start’)console.log(‘setTimeout’)console.log(‘promise1’)
    console.log(‘script end’)console.log(‘promise1’)

习题18

console.log('script start');setTimeout(function() {console.log('timeout1');
}, 10);new Promise(resolve => {console.log('promise1');resolve();setTimeout(() => console.log('timeout2'), 10);
}).then(function() {console.log('then1')
})console.log('script end');
//script start、promise1、script end、then1、timeout1、timeout2

习题18解析

首先,事件循环从宏任务 (macrotask) 队列开始,最初始,宏任务队列中,只有一个 script(整体代码)任务;当遇到任务源 (task source)
时,则会先分发任务到对应的任务队列中去。所以,就和上面例子类似,首先遇到了console.log,输出 script start; 接着往下走,遇到 setTimeout 任务源,将其分发到任务队列中去,记为 timeout1; 接着遇到
promise,new promise 中的代码立即执行,输出 promise1, 然后执行 resolve ,遇到 setTimeout ,将其分发到任务队列中去,记为 timemout2, 将其 then 分发到微任务队列中去,记为
then1; 接着遇到 console.log 代码,直接输出 script end 接着检查微任务队列,发现有个 then1 微任务,执行,输出then1 再检查微任务队列,发现已经清空,则开始检查宏任务队列,执行 timeout1,输出
timeout1; 接着执行 timeout2,输出 timeout2 至此,所有的都队列都已清空,执行完毕。其输出的顺序依次是:script start, promise1, script end, then1, timeout1,
timeout2。

有个小 tip:从规范来看,microtask 优先于 task 执行,所以如果有需要优先执行的逻辑,放入microtask 队列会比 task 更早的被执行。 最后的最后,记住,JavaScript
是一门单线程语言,异步操作都是放到事件循环队列里面,等待主执行栈来执行的,并没有专门的异步执行线程。

习题19

console.log(1)
setTimeout(function() {console.log(2)
},0)
setTimeout(function() {console.log(3)
},0)
console.log(4)
// 1 4 2 3

习题19解析

习题20

function fun1(){console.log(1)
}
function fun2(){
console.log(2)
fun1()
console.log(3)
}
fun2()
// 2 1 3

习题20解析

习题21

function func1(){console.log(1)
}
function func2(){setTimeout(()=>{console.log(2)},0)func1()console.log(3)
}
func2()
// 1 3 2

习题21解析

习题22

var p = new Promise(resolve=>{console.log(4) //这里没有执行p也要有输出 所以4是最开始的resolve(5)
})
function func1(){console.log(1)
}
function func2(){setTimeout(()=>{console.log(2)},0)func1()console.log(3)p.then(resolve=>{console.log(resolve)})
}
func2()
//4 1 3 5 2

习题22解析

习题21

console.log('start')
const interval = setInterval(() => {console.log('setInterval')
}, 0)
setTimeout(() => {console.log('setTimeout 1')Promise.resolve().then(() => {console.log('promise 1')}).then(() => {console.log('promise 2')}).then(() => {setTimeout(() => {console.log('setTimeout 2')Promise.resolve().then(() => {console.log('promise 3')}).then(() => {console.log('promise 4')}).then(() => {clearInterval(interval)})}, 0)})console.log('time end')
}, 0)
Promise.resolve().then(() => {console.log('promise 5')
}).then(() => {console.log('promise 6')
})// start
// promise 5
// promise 6
// setInterval
// setTimeout 1
// time end
// promise 1
// promise 2
// setInterval
// setTimeout 2
// setInterval
// promise 3
// promise 4

习题22解析

解析: (1)先按照 macrotask 和 microtask 划分代码:

    console.log('start')

setInterval 是 macrotask,其回调函数在 microtask 后执行

    const interval = setInterval(() => {console.log('setInterval')}, 0)

setTimeout 是 macrotask,其回调函数放在下一车(cycle 2)执行

 setTimeout(() => ... , 0)

Promise.resolve () 的两个 then () 是 microtask

    Promise.resolve()//microtask.then(() => {console.log('promise 5')})//microtask.then(() => {console.log('promise 6')})

(2)第一班车(cycle 1):
进栈

第一个 macrotask 是 setInterval,回调函数放下一车(cycle 2)的开头执行, 第二个 macrotask 是 setTimeout,回调函数放下下一车(cycle 3)的开头执行,

清空栈, 输出:start 执行 microtasks,直至清空该队列,即 Promise.resolve () 的两个 then (), 输出:promise 5 promise 6

(3)第二班车(cycle 2): 执行 setInterval 的回调, 输出:setInterval, 同时下一个 setInterval 也是 macrotask 但要放到 下下下一车(cycle 4)执行回调,即
下下一车(cycle 3)setTimeout 的后面

此时 setInterval 中没有 microtasks,所以该队列是空的,故进行下一车(cycle 3)

(4)第三班车(cycle 3) 执行 setTimeout 的回调, 输出 setTimeout 1 执行 microtasks,直至清空该队列,即 Promise.resolve () 的第一个和第二个 then (),

输出:promise 1 promise 2

而 第三个 then () 中的 setTimeout 是 macrotask ,放到下下下下一车(cycle 5)执行回调, 第四个 then () 是紧跟着第三个 then () 的,所以在 下下下下一车(cycle 5)执行

此时 microtasks 已空,故进行下一车(cycle 4)

(5)第四班车(cycle 4) 由(3)得,执行 setInterval , 输出:setInterval

此时 setInterval 中没有 microtasks,所以该队列是空的,故进行下一车(cycle 5)

同时下一个 setInterval 也是 macrotask 但要放到 下下下下下一车(cycle 6)执行回调,

(6)第五班车(‘cycle 5’) 由(4)得,执行 setTimeout 输出:setTimeout 2

执行 microtasks,直至清空该队列,即 Promise.resolve () 的第一个和第二个 then (),

输出:promise 3 promise 4

接着执行第三个 then () --> clearInterval(interval),将下下下下下一车(cycle 6)要执行回调的 setInterval 清除

此时 microtasks 已空, 同时整段代码执行完毕。

相关内容

热门资讯

安卓系统43适配软件,软件升级... 你有没有发现,你的安卓手机最近是不是有点儿“水土不服”?别急,别急,让我来给你揭秘为什么你的安卓系统...
安卓系统有车载系统吗吗,智能驾... 你有没有想过,当你坐在车里,享受着旅途的悠闲时光,手机上的安卓系统是不是也能派上用场呢?没错,我就要...
安卓8.1系统解锁方法,畅享自... 你有没有想过,你的安卓手机里隐藏着无数的小秘密?比如,解锁安卓8.1系统,就能让你的手机焕发出全新的...
安卓系统怎么打开邮件,安卓系统... 你有没有想过,每天那么多邮件,怎么才能快速打开它们呢?尤其是当你用的是安卓系统手机的时候。别急,今天...
封闭安卓系统安装软件,一步到位... 你有没有想过,为什么你的安卓手机里有些软件只能通过官方渠道安装呢?今天,就让我带你一探究竟,揭开封闭...
小米mipad升级安卓系统,解... 你有没有发现,最近小米Mipad的安卓系统升级可是个大热门呢!这不,我就迫不及待地来和你聊聊这个话题...
哪个安卓系统体验好,揭秘安卓系... 你有没有想过,手机里的安卓系统就像是个大厨,不同的版本就是不同的拿手好菜,有的让你回味无穷,有的却让...
安卓系统开发测试,全方位技术解... 你有没有想过,那个陪伴你每天刷手机、玩游戏、办公的安卓系统,是怎么从无到有,一步步成长起来的呢?今天...
安卓系统怎么查配置,轻松掌握设... 你有没有想过,你的安卓手机里藏着多少秘密?别小看这些配置信息,它们可是了解你手机性能的“小侦探”呢!...
pve下安装安卓系统,PVE环... 你有没有想过,在你的PVE服务器上安装一个安卓系统呢?听起来是不是有点酷炫?想象你的服务器不仅能够运...
安卓手机安装虹膜系统,安卓手机... 你有没有想过,你的安卓手机还能这样玩?没错,就是安装虹膜系统!听起来是不是有点酷炫?别急,让我带你一...
小米论坛原生安卓系统,深度解析... 你有没有想过,你的手机系统其实可以更加纯粹、更加原生?今天,就让我带你走进小米论坛,一探究竟,看看那...
安卓怎么装iphone系统,轻... 你是不是也和我一样,对安卓手机上的iPhone系统充满了好奇?想象那流畅的界面、强大的性能,还有那独...
模拟器系统安卓,打造移动应用开... 你有没有想过,在手机上也能体验到电脑游戏的快感?没错,这就是安卓模拟器系统的魅力所在!今天,就让我带...
安卓系统清理系统更新包,提升运... 手机里的安卓系统是不是越来越慢了?别急,今天就来给你支个招,让你的安卓手机焕然一新!那就是——清理系...
酷开系统是安卓系统不,深度解析... 亲爱的读者,你是否曾好奇过,那些在我们手机、电视上运行得风生水起的操作系统,它们之间究竟有何不同?今...
小说系统类游戏安卓,安卓世界逆... 你有没有想过,在手机上玩一款能让你瞬间穿越到小说世界的游戏?想象你不再是旁观者,而是故事的主角,那种...
安卓系统网页上传文件,安卓系统... 你有没有遇到过这种情况:手机里存了好多文件,想要上传到网页上分享,却发现安卓系统的操作有点儿复杂?别...
xp系统能刷安卓系统吗,体验全... 你有没有想过,你的老XP系统是不是也能玩转安卓的乐趣呢?没错,今天就来聊聊这个话题,看看XP系统能不...
安卓系统图标修改方法,让你的手... 你有没有发现,手机里的安卓系统图标总是那么单调乏味?是不是也想给它们换上新鲜的衣服,让手机界面焕然一...