This week’s interview questions list:
- What is closure? What is the function of closures?
- Implement Promise.all method
- What are the ways to load js scripts asynchronously?
- Please implement a Flattened Deep function to flatten nested arrays
- What are the characteristics of iterated objects?
More quality articles to stamp on: https://github.com/YvetteLau/ …
15. What is closure? What is the function of closures?
What is closure?
Closures are functions that have access to variables in the scope of another function. The most common way to create closures is to create another function within a function.
Create a closure
function foo() {
var a = 2;
return function fn() {
console.log(a);
}
}
let func = foo();
func(); //输出2
Closures allow functions to continue to access the lexical scope at the time of definition. Thanks to fn, the scope inside foo will not be destroyed after foo () is executed.
No matter by what means the internal function is passed outside its lexical scope, it will hold a reference to the original definition scope and will use closures wherever it is executed. For example:
function foo() {
var a = 2;
function inner() {
console.log(a);
}
outer(inner);
}
function outer(fn){
fn(); //闭包
}
foo();
The Function of Closure
- Can access the lexical scope of the function definition (prevent it from being recycled).
- Privatization variable
function base() {
let x = 10; //私有变量
return {
getX: function() {
return x;
}
}
}
let obj = base();
console.log(obj.getX()); //10
- Simulate block-level scope
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = (function(j){
return function () {
console.log(j);
}
})(i);
}
a[6](); // 6
- Create module
function coolModule() {
let name = 'Yvette';
let age = 20;
function sayName() {
console.log(name);
}
function sayAge() {
console.log(age);
}
return {
sayName,
sayAge
}
}
let info = coolModule();
info.sayName(); //'Yvette'
Module mode has two prerequisites (from JavaScript you don’t know)
- There must be an external enclosing function that must be called at least once (each call creates a new module instance)
- Closed functions must return at leastOneInternal functions, so that internal functions can form closures in private scopes and can access or modify private states.
Disadvantages of Closures
Closures cause variables of functions to be kept in memory all the time, and too many closures may cause memory leaks.
16. implement Promise.all method
Before implementing the Promise.all method, we must first know the functions and characteristics of Promise.all, because we can write the implementation further only when the functions and characteristics of Promise.all are clear.
Promise.all function
Promise.all(iterable)
Returns a new Promise instance. This instance is found initerable
All within the parameterpromise
Allfulfilled
Or the parameter does not containpromise
, the state changes tofulfilled
; If one of the parameterspromise
There is one failurerejected
This instance callback failed because of the first failurepromise
Returns the result of the.
let p = Promise.all([p1, p2, p3]);
The state of P is determined by P1, P2 and P3 and is divided into the following: There are two situations:
(1) Only p1, p2 and p3 becomefulfilled
, the state of p will becomefulfilled
In this case, the return values of p1, p2 and p3 form an array and are passed to the callback function of p.
(2) As long as one of p1, p2, p3 isrejected
, the state of p becomesrejected
The return value of the first reject instance is passed to the callback function of p.
Features of Promise.all
The return value of Promise.all is a promise instance
- If the passed-in parameter is an empty iterated object,
Promise.all
MeetingSynchronizationA that returns a completed statepromise
- If the parameter passed in does not contain any promise,
Promise.all
MeetingAsynchronousA that returns a completed statepromise
- In other cases,
Promise.all
Return onePendingState ofpromise
.
The status of promise returned by Promise.all
- If promise in the passed-in parameters all become complete,
Promise.all
Returnedpromise
Become completed asynchronously. - If one of the parameters passed in
promise
Failure,Promise.all
The result of the failure is asynchronously given to the callback function of the failed state, regardless of the others.promise
Is it complete - In any case,
Promise.all
Returnedpromise
The result of the completion status of is an array
Promise.all implementation
Consider only the case where the passed-in parameters are arrays
/** 仅考虑 promises 传入的是数组的情况时 */
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
if (promises.length === 0) {
resolve([]);
} else {
let result = [];
let index = 0;
for (let i = 0; i < promises.length; i++ ) {
//考虑到 i 可能是 thenable 对象也可能是普通值
Promise.resolve(promises[i]).then(data => {
result[i] = data;
if (++index === promises.length) {
//所有的 promises 状态都是 fulfilled,promise.all返回的实例才变成 fulfilled 态
resolve(result);
}
}, err => {
reject(err);
return;
});
}
}
});
}
The code on MDN can be used for testing
Consider the iterable object
Promise.all = function (promises) {
/** promises 是一个可迭代对象,省略对参数类型的判断 */
return new Promise((resolve, reject) => {
if (promises.length === 0) {
//如果传入的参数是空的可迭代对象
return resolve([]);
} else {
let result = [];
let index = 0;
let j = 0;
for (let value of promises) {
(function (i) {
Promise.resolve(value).then(data => {
result[i] = data; //保证顺序
index++;
if (index === j) {
//此时的j是length.
resolve(result);
}
}, err => {
//某个promise失败
reject(err);
return;
});
})(j)
j++; //length
}
}
});
}
Test code:
let p2 = Promise.all({
a: 1,
[Symbol.iterator]() {
let index = 0;
return {
next() {
index++;
if (index == 1) {
return {
value: new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
}), done: false
}
} else if (index == 2) {
return {
value: new Promise((resolve, reject) => {
resolve(222);
}), done: false
}
} else if(index === 3) {
return {
value: 3, done: false
}
}else {
return { done: true }
}
}
}
}
});
setTimeout(() => {
console.log(p2)
}, 200);
17. What are the ways to load js scripts asynchronously?
<script>
Added to labelasync
(html5) ordefer
(html4) attribute, the script will be loaded asynchronously.
<script src="../XXX.js" defer></script>
defer
Andasync
The difference lies in:
-
defer
When the normal rendering of the whole page in memory is finished (DOM structure is fully generated and other scripts are executed), it is executed before window.onload; -
async
Once the download is complete, the rendering engine will stop rendering and continue rendering after executing this script. - If there are multiple
defer
Scripts are loaded in the order in which they appear on the page - Multiple
async
Scripts cannot guarantee the loading order
Dynamic creationscript
Label
Dynamically createdscript
, settingssrc
The JS file will not start downloading until it is added to the document.
let script = document.createElement('script');
script.src = 'XXX.js';
// 添加到html文件中才会开始下载
document.body.append(script);
XHR asynchronous loading JS
let xhr = new XMLHttpRequest();
xhr.open("get", "js/xxx.js",true);
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
eval(xhr.responseText);
}
}
18. Please implement a Flattened Deep function to flatten nested arrays
Using Array.prototype.flat
ES6 added to array instancesflat
Method, used to “flatten” nested arrays into one-dimensional arrays. This method returns a new array and has no effect on the original array.
flat
The default is to “flatten” only one layer. If you want to “flatten” multi-layer nested arrays, you need to giveflat
Pass an integer indicating the number of layers you want to flatten.
function flattenDeep(arr, deepLength) {
return arr.flat(deepLength);
}
console.log(flattenDeep([1, [2, [3, [4]], 5]], 3));
When the passed integer is greater than the number of nested layers of the array, the array will be flattened into a one-dimensional array, and the maximum number JS can represent isMath.pow(2, 53) - 1
So we can define it this wayflattenDeep
Function
function flattenDeep(arr) {
//当然,大多时候我们并不会有这么多层级的嵌套
return arr.flat(Math.pow(2,53) - 1);
}
console.log(flattenDeep([1, [2, [3, [4]], 5]]));
Leveraging reduce and concat
function flattenDeep(arr){
return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);
}
console.log(flattenDeep([1, [2, [3, [4]], 5]]));
Using stack to Infinitely Anti-nest Multi-level Nested Arrays
function flattenDeep(input) {
const stack = [...input];
const res = [];
while (stack.length) {
// 使用 pop 从 stack 中取出并移除值
const next = stack.pop();
if (Array.isArray(next)) {
// 使用 push 送回内层数组中的元素,不会改动原始输入 original input
stack.push(...next);
} else {
res.push(next);
}
}
// 使用 reverse 恢复原数组的顺序
return res.reverse();
}
console.log(flattenDeep([1, [2, [3, [4]], 5]]));
19. What are the characteristics of iterated objects
ES6 stipulates that the defaultIterator
The interface is deployed in the of the data structureSymbol.iterator
Attribute, in other words, a data structure can be considered as long as it hasSymbol.iterator
Properties (Symbol.iterator
The method corresponds to a traverser generation function and returns a traverser object), then it can be considered iterated.
Characteristics of Iterative Objects
- Have
Symbol.iterator
Attributes,Symbol.iterator()
Returns a traverser object - Can be used
for ... of
Cycle through
let arry = [1, 2, 3, 4];
let iter = arry[Symbol.iterator]();
console.log(iter.next()); //{ value: 1, done: false }
console.log(iter.next()); //{ value: 2, done: false }
console.log(iter.next()); //{ value: 3, done: false }
Native toIterator
The data structure of the interface:
- Array
- Map
- Set
- String
- TypedArray
- Arguments object for function
- NodeList object
Customize an Iterative Object
As we said above, an object only has the correctSymbol.iterator
Property, then it is iterated, so we can addSymbol.iterator
Make it iterative.
let obj = {
name: "Yvette",
age: 18,
job: 'engineer',
*[Symbol.iterator]() {
const self = this;
const keys = Object.keys(self);
for (let index = 0; index < keys.length; index++) {
yield self[keys[index]];//yield表达式仅能使用在 Generator 函数中
}
}
};
for (var key of obj) {
console.log(key); //Yvette 18 engineer
}
Reference articles:
[2]Promise
[3]Iterator
Thank you for your friends’ willingness to spend precious time reading this article. If this article gives you some help or inspiration, please don’t be stingy with your praise and Star. Your affirmation is my greatest motivation to move forward.https://github.com/YvetteLau/ …
Recommend to pay attention to my public number: