Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

2020 ES6 interview questions How much do you know?


May 31, 2021 Article blog


Table of contents


preface

In the interview, ES6 has almost become a mandatory question, ES6 is still ambiguous small partners read this article will no longer be confused, suggest collection.

1. Let variable declarations and attributes

Declare the variable

 let a;
 let b, c, d;
 let e = 1;
 let f = 2, g = 3; 

characteristic

  • Claims cannot be repeated
  • Block-level scopes are only valid at the block-level scope
  • There is no variable promotion
  • Does not affect the scope chain

2.const constant declaration and attribute

characteristic

  • There must be an initial value
  • The general constant uses capitals
  • The value of the constant cannot be modified
  • It is also a block-level scope
  • For array and object modifications, no changes to constants are counted and no errors are reported (arrays and objects can be modified, pointing to addresses that have not changed)

3. Deconstruction assignment of the variable

The deconstruction of the array

const RNG = ['uzi', 'mlxg', 'letme', 'ming']
let [a, b, c, d] = RNG;// 每个值就是数组的位置对应的值

The deconstruction of the object

const UZI= {
  name: '自豪',
  age: 22,
  love: 'LOL',
  lol: function(){
    alert('打lol')
  }
}
let {name, age, love} = UZI;// 每个值是对象中对应的值
let {lol} = UZI;
lol();// 使用

4. Template string ''

Line breaks can appear directly in the content, and single-quote double-quote content cannot be stitched directly with line breaks (need to be stitched through quotation marks plus signs)

let str = `lol s10
      tes 是冠军`;// 可以这样直接使用换行符

Stitch variables directly $

let lol = 'lol十周年';
let uzi = `${lol} 中国队夺冠`

5. Shorthand for the object

let name = 'zhangning187';


let change = function(){
  console.log('努力改变');
}


const supwisdom = {
  name,
  change
}

6. Arrow functions and declaration features are >

let fn = (a, b) => {
  return a + b;
}
fn(1, 2);// 3

peculiarity

  • 1.this is static, this is always the thais value under the scope in which the function is declared, and he does not have his own this
  • 2. Cannot be instantiated as a construction object
  • 3. You cannot use the arguments variable
  • 4. Shorthand for arrow function

Omit the parenthesis, which can be omitted when the shape is there and there is only one

let add = n => {
        return n*2;
      }

Omitting braces, when there is only one statement in the body of code, return must be omitted, and the result of the statement's execution is the return value of the function

let add = n => n*2;

7. The default value of the function argument

The initial value of the parameter

function add(a, b, c = 10) {// 当不传递c的时候,c的默认值是10,尽量把具有默认值的参数放在后面
  return a + b + c;
}
add (1, 2);// 13

Combined with deconstruction assignments

function con({name, age, love, height = '18'}) {// 还可以给默认值
  console.log(age);// 24
  console.log(height);// 没有传递,使用默认值 18
}
con({
  name: 'zhangning187',
  age: 24,
  love: 'js'
})

8.rest parameter

Used to get arguments for arguments in place of arguments

The rest argument is an array unlike the argions in es5, where arguments are an object

How to get arguments

function data(a, b, ...args) {// rest 参数必须放到参数的最后面
    console.log(a);// 1
    console.log(b);// 2
    console.log(args);// [3, 4, 5, 6, 7]
}
data(1, 2, 3, 4, 5, 6, 7);

9. Extended operator ...

You can convert an array to a comma-separated sequence of arguments, split an array, and pass items to functions as separate sequences of arguments

const RNG = ['UZI', 'MLXG', 'LETME', 'MING'];
console.log(...RNG)// UZI MLXG LETME MING  解构之后的序列
console.log(RNG);// ['UZI', 'MLXG', 'LETME', 'MING']  返回的是一个数组
const a = [1,2], b=[3,6];
const c = [...a, ...b];// [1, 2, 3, 6]

10. Symbol's new raw data type represents a unique value

He is the seventh data type in the JavaScript language, a string-like data type

peculiarity

  • 1. Symbol's value is unique and is used to resolve naming conflicts
  • 2. Symbol values cannot be calculated with other data, nor can they be operated by themselves . . . .
  • 3. Symbol-defined object properties cannot be traversed using for in loops, but you can use Reflect.nowKeys to get all the key names of the objects

//创建Symbol
let s = Symbol();// s不可见,在内部实现唯一性
let s2 = Symbol('zhangning187');// 这里面的字符串只是一个标志,Symbol返回的值都是唯一的
let s3 = Symbol('zhangning187');
console.log(s2 == s3);// false,确定唯一性


//Symbol.for()方法创建,这是一个对象,这种方式可以得出唯一的Symbol值
let s6 = Symbol.for('zhangning187');
let s8 = Symbol.for('zhangning187');
console.log(s6 ==s8);// true  得到唯一的Symbol值

The object adds properties of the Symbol type

let zn = {


      up: function(){},
      down: function(){},
      name: 'zhangning187',
      age: 24
    }
    // 向对象zn中添加 up down 方法
    // zn.up = function(){}// 这个可以添加但是不确定zn中是否存在up方法,可能会覆盖原来的up方法
    // 这时候需要考虑通过Symbol添加唯一的方法
    // 声明一个对象
    let methods = {


      up: Symbol(),
      down: Symbol()
    }
    zn[methods.up] = function(){


      console.log('我可以爬楼');
    }
    zn[methods.down] = function(){


      console.log('我可以下楼');
    }
    console.log(zn);// 已经添加唯一的方法 up down

    
    let UZI = {


      name: '自豪',
      // Symbol(): function(){},// 这里不能这样直接使用, Symbol()是一个表达式,是一个动态的
      [Symbol('lol')]: function(){


        console.log('我会打lol');
      },
      [Symbol('篮球')]: function(){// Symbol()中还可以添加描述字符串


        console.log('我可以打篮球')
      }
    }
    console.log(UZI);

11. Iterator

An iterator is an interface that provides a unified access mechanism for a variety of different data structures, and any data structure can be traversed as long as the Iterator interface is deployed

1.ES6 creates a new traversal command for... O f loop, Iterator interface provides for... of consumption

2. Native data with iterator interface

Array Arguments Set Map String TypedArray NodeList

3. How it works

  • a Create a pointer object that points to the starting position of the current data structure
  • b The first time the object's next method is called, the pointer automatically points to the first member of the data structure
  • c Next, the next method is called continuously, and the pointer moves back until it points to the last member
  • d Each time the next method is called, an object containing the value and doone properties is returned

When customizing the traversal data, think of the iterator

12. The declaration and call of the generator function

The generator function is an asynchronous programming solution provided by ES6, which, unlike traditional functions, is a special function

// 声明    
function * gen(){// * 可以靠左,也可以靠右,还可以放在中间
  // console.log('hello');
  yield '2020lpl牛批';// yield 语句可以算作函数代码的分隔符
  let two = yield ‘uzi 退役了’;
  console.log(two);
  yield '湖人总冠军';
}
// 执行
let iterator = gen();
// console.log(iterator);// 返回结果是一个迭代器对象
console.log(iterator.next());// 需要执行迭代器对象中的next()方法,才会执行生成器函数
console.log(iterator.next());// 每个next()只会执行里面一个yield语句,这个会输出 ‘uzi 退役了’
// 传递参数 参数将作为上一个yield语句的返回结果
console.log(iterator.next('AAA'));// 第三次调用传递的参数将作为第二个yield 的返回结果 打印为AAA
// 使用for of循环遍历输出
for(let v of gen()){
  console.log(v);// 依次输出yield语句中的值
}

Case: 1s output 111 2s output 222 3s output 333

    function one(){
      setTimeout(()=>{
        console.log('111')
        iterator.next();
      }, 1000)
    }
    function two(){
      setTimeout(()=>{
        console.log('111')
        iterator.next();
      }, 1000)


    }
    function three(){
      setTimeout(()=>{
        console.log('111')
      }, 1000)


    }
    // 生成器函数
    function * gen(){
      yield one();
      yield two();
      yield three();
    }
    // 调用生成器函数
    let iterator = gen();
    iterator.next();

13. Promise basic use

Promise is a constructor that encapsulates asynchronous operations and can get the results of their success or failure

  • 1, Promise constructor Promise (excutor)
  • 2. Promise.prototype.then has two arguments, both of which are functions,

The Promise object successfully executes the first function in the ten and fails to execute the second function

  • 3、 Promise.prototype.catch

    // 实例化
    const p = new Promise((resolve, reject) => {
      // 通过resolve,reject这两个函数来改变Promise对象的状态,
      // resolve会改变p的状态为成功,reject会改变p的状态为失败,然后去执行then里面的方法
      // 执行异步操作,以定时器为例,定时器也是异步
      setTimeout(()=>{
        //let data = '异步执行成功';
        // resolve(data);// 调用resolve函数, p会变成一个成功的状态,会执行then中的第一个方法
        let err = '执行失败';
        reject(err);// 调用reject函数,p会变成一个失败的状态,会执行then中的第二个方法
      }, 1000)
    })
     // 成功会调用 promise 对象 then 方法
    p.then(value => {// 成功
      // console.log(value);// 控制台打印:异步执行成功
    }, reason => {// 失败
      console.error(reason)
    })

Promise.prototype.then feature

    // then方法的返回结果是Promise对象,对象状态由回调函数的执行结果决定
    const p = new Promise((resolve, reject) => {
      setTimeout(()=>{
        resolve('成功');
        reject('失败');
      }, 1000);
    });
    // then 的返回结果是一个Promise对象,就是result也是一个Promise对象,它的状态由函数的执行结果决定的
    const result  = p.then(value => {
      console.log(value);
      // 1.如果返回的结果是 非Promise 类型的属性,状态为成功,返回值return 中的值
      // 如果不写return,函数内部不写return返回结果是undefined,也不是Promise对象,状态也是成功
      // return 123;
      // 2.是 promise 对象, 该对象返回的状态就决定了then方法返回promise对象状态
      return new Promise((resolve, reject)=>{
        // resolve('ok');// then方法返回promise对象状态为成功
        reject('no');// then方法返回promise对象状态为失败
      })
      // 3.抛出错误  then方法返回promise对象状态为失败,错误值为抛出错误的值
      throw new Error('出错了');
    }, reason => {
      console.err(reason);
    });
    console.log(result);
    // 综上总结,then方法可以链式调用  可以改变回调域的现象
    p.then(value=>{}, reason=>{})
      .then(value()=>{}).then();

For example, after multiple requests have been returned, get the data in them

    const p = new Promise((resolve, reject)=>{
      resolve('第一次返回成功')
    });
    p.then(value=>{
      return new Promise((resolve, reject)=>{
        resolve([value, '第二次返回成功'])
      });
    }).then(value=>{
      return new Promise((resolve, reject)=>{
        resolve([...value, '第三次返回成功'])
      });
    }).then(value=>{
      console.log(value);// 返回值为三次请求都返回成功以后的值
    });

14. Collection set

The new data structure Set (collection), which is similar to an array, with members whose values are unique, implements the iterator interface, so you can use extension operators and for of traversals

The properties and methods of the collection

  • 1 size returns the number of elements in the collection
  • 2 add adds a new element that returns the current collection
  • 3 Delete deletes the element and returns the boolean value
  • 4 has detects whether an element is contained in the collection, returning the boolean value
  • 5 clear empty

    // 声明
    let s = new Set();
    let s2 = new Set([1, 2, 3, 6, 7]);
    console.log(s2);// 5
    s2.add(8);// 添加新元素 
    console.log(s2);// 输出 {1, 2, 3, 6, 7, 8}
    s2.delete(8);
    console.log(s2);// 输出 {1, 2, 3, 6, 7}
    console.log(s2.has(8));// false
    // s2.clear();// 清空


    let arr = [1, 2, 3, 3, 3, 6, 6, 8];
    let arr2 = [1, 3, 6, 7, 8];
    // 数组去重
    let result = [...new Set(arr)];
    // 交集
    let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
    // 并集
    let result = [...new Set([...arr, ...arr2])];
    // 差集 arr有arr2中没有
    let result = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));

15.Map collection

Similar to an object, it is also a collection of key value pairs, but keys are not limited to strings, and various types of values, including objects, can be used as keys.

Map also implements the iterator interface, so you can use extension operators and for of traversal

  • 1 size returns the number of elements of map
  • 2 set adds a new element that returns the current Map
  • 3 get returns the key value of the key name object
  • 4 has detects whether an element is included in the Map, returning the boolean value
  • 5 clear emptys the collection and returns to the underfined

    // 声明
    let m = new Map();
    m.set('name', 'zhangning');
    m.set('change', function(){console.log('变得更努力')});// 键 change 值 一个function
    let key = {company: 'supwisdom'}; 
    m.set(key, [1, 2, 3]);//键 对象 值 数组
    m.size;// 获取m个数
    m.delete('name');// 删除键值对
    m.get('change');// 获取键对应的值
    // m.clear();// 清空
    for(let v of m){console.log(v);}

16.class class

Classes can be defined, and the new class writing simply makes the writing of object prototypes clearer and more like object-oriented programming syntax.

  • 1 class declaration class
  • 2 constructor defines constructor initialization
  • 3 extends inherit the parent class
  • 4 Super calls the parent construction method
  • 5 static defines static methods and properties
  • 6 The parent method can be overridden

es5 instantiates the object by constructor

    // 人
    function People(name, sex) {
      this.name = name;
      this.sex = sex;
    }
    // 这个height这种添加方式是属于函数对象的,不属于实例对象,这样的属性称之为静态成员
    People.height = '180';
    People.prototype.height1 = '100';
    // 添加方法
    People.prototype.play = function(){
      console.log('打篮球');
    }
    let zn = new People('zhangning', '男');
    zn.play();// 输出 打篮球
    console.log(zn);
    console.log(zn.height);// 输出 undefined 
    console.log(zn.height1);// 输出 100,必须通过prototype添加才能添加到实例对象上

Implemented through class

    class People{
      // 静态属性 static,对于static 标注的方法属于类,不属于实例对象
      static height = '100';
      static change(){
        console.log('我可以改变世界');
      }
      // 构造方法 名字不能更改(在使用new People的时候会自动执行实例对象上的constructor方法)       
      constructor(name, sex){
        this.name = name;
        this.sex = sex;
      }
      // 添加方法必须使用该语法,不能使用es5的完整形式(play: function(){} 这种形式不支持,必须使用play()形式)
      // 成员属性
      play(){
        console.log('打篮球');
      }
    }
    let zn = new People('zhangning', '男');
    console.log(zn);
    console.log(zn.height);// undefined  static 标注的方法属于类,不属于实例对象
    console.log(People.height);// 100  

Inheritance is implemented using the es5 constructor

    // 举例 chinese 继承 People 属性
    function People(name, sex) {
      this.name = name;
      this.sex = sex;
    }
    People.prototype.play = function(){
      console.log('打LOL');
    }
    function Student(name, sex, like, height){
      // 通过call方法,改变this值,this指向chinese中的this,也就是chinese的一个实例对象
      People.call(this, name, sex);
      this.like = like;
      this.height = height;
    }
    // 设置子集构造函数原型
    Student.prototype = new People;// 这样就会有父级的一个方法
    Student.prototype.constructor = Student;// 做一个校正,没有这行代码也无所谓
    // 声明子类方法
    Student.prototype.photo = function(){
      console.log('去拍照');
    }
    // 实例化
    const zn = new Student('zhangning', '男', '打篮球', '187');
    console.log(zn)

Use the es6 class class to implement inheritance and parent method overrides

    // 声明父类
    class People{
      // 父类构造方法
      constructor(name, sex) {
        this.name = name;
        this.sex = sex;
      }
      // 父类成员属性
      play(){
        console.log('打LOL');
      }
    }
    // 声明子类 使用extends 继承父类
    class Student extends People {
      // 构造方法
      constructor(name, sex, like, height){
        super(name, sex);// super 就是父类的constructor构造函数,这样调用
        this.like = like;
        this.height = height;
      }
      photo(){
        console.log('去拍照');
      }
      // 对父类中的play方法进行重写,子类是不能去调用父类的同名方法的,


      play(){
        // super(); 不允许,在普通的成员方法里面是不能出现super()去调用父类的同名方法的,会报错,只能完全重写
        console.log('我会打LOL,还会打篮球');
      }
    }
    const zn = new Student('zhangning', '男', '打篮球', '187');
    console.log(zn)

Getter and setter settings in class

    class People{
      get like(){
        return '打篮球';
      }
      set like(newVal){
        // 通过传过来的newVal值,进行操作,改变 like
        console.log('改变like值');
      }
    }
    let p = new People();
    console.log(p.like)// 输出 打篮球
    p.like = 'LOL';// 然后通过 set like 进行操作

17. Object numerical extension

Object.is

Determines whether the two values are exactly equal

Object.is(1, 1);// true

It's very similar to , and the only difference is that NaN is false and Object.is (NaN, NaN) is true

Object.assign

The merge of objects

const c1 = {name: 'znn'};
const c2 = {name: 'zhangning', height: 187};
Object.assign(c1, c2);// 如果两个对象中存在相同属性,c2 中覆盖c1中的属性内容

Object.setPrototypeOf

Set up the prototype object

const zn = {
    name: 'zhangning',
}
const p = {
    h: true,
    sfsfdf: 'fasfasdf'
}
Object.setPrototypeOf(zn, p);// 设置 zn 的原型里面有 p
Object.getPrototypeOf(zn);// 获取 zn 的原型
console.log(zn);// 打印看下

18. Array extension

Array.from()

The Array.from method is used to turn two types of objects into real arrays: array-like objects and objects that can be traversed (iterable), including ES6's new data structure Set and Map.

let arrayLike = {  
  '0': 'a',  
  '1': 'b',  
  '2': 'c',  
  length: 3  
};  
// ES5 的写法  
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']  
// ES6 的写法  
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']  

  
// NodeList 对象  
let ps = document.querySelectorAll('p');  
Array.from(ps).forEach(function (p) {  
  console.log(p);  
});  
// arguments 对象  
function foo() {  
var args = Array.from(arguments);  
// ...  
}  


//字符串转换为字符数组str.split('')  
Array.from('hello')  // ['h', 'e', 'l', 'l', 'o']  
let namesSet = new Set(['a', 'b'])  
Array.from(namesSet) // ['a', 'b']  

  
Array.from({ length: 3 });  // [ undefined, undefined, undefined ] 

For browsers that have not yet deployed this method, you can replace it with the Array.prototype.slice method:

const toArray = (() =>
  Array.from ? Array.from : obj => [].slice.call(obj)
)();

Array.from can also accept the second argument, which acts like an array's map method, to process each element and put the processed value into the returned array.

Array.from(arrayLike, x => x * x);  
//  等同于  
Array.from(arrayLike).map(x => x * x);  
Array.from([1, 2, 3], (x) => x * x)  
// [1, 4, 9]  
//Array.from回调函数
var arr1 = Array.from([1,2,3], function(item){
    return item*item;
});
var arr2 = Array.from([1,2,3]).map(function(item){
    return item*item;
});
var arr3 = Array.from([1,2,3], (item) => item*item);


console.log(arr1); //[ 1, 4, 9 ]
console.log(arr2); //[ 1, 4, 9 ]
console.log(arr3); //[ 1, 4, 9 ]

It's worth noting that the extension operator (...) You can also convert some data structures into arrays.

// arguments 对象  
function foo() {  
  var args = [...arguments];  
}  
// NodeList 对象  
[...document.querySelectorAll('div')]  

Array.of()

The Array.of method is used to convert a set of values to an array. A rray.of always returns an array of parameter values. If there are no arguments, an empty array is returned.

Array.of can basically be used as a substitute for Array() or new Array() and there are no overloads due to different parameters. Its behavior is very uniform.

The main purpose of this method is to compensate for the deficiency of the array constructor Array(). Because the number of parameters is different, the behavior of Array() is different

Array() // []  
Array(3) // [, , ,]  
Array(3, 11, 8) // [3, 11, 8]  

  
Array.of() // []  
Array.of(3) // [3]  
Array.of(3, 11, 8) // [3,11,8]  

  
Array.of(3).length // 1   
Array.of(undefined) // [undefined]  
Array.of(1) // [1]  
Array.of(1, 2) // [1, 2]  

The Array.of method can be implemented with the following code simulation:

function ArrayOf(){
  return [].slice.call(arguments);
}

find() and findIndex()

The find method of an array instance to find the first eligible array member. I ts argument is a callback function, and all array members execute the callback function in turn until the first member with a true return value is found, and then the member is returned. If there are no eligible members, the underfined is returned.

[1, 4, -5, 10].find((n) => n < 0)  
// -5  
[1, 5, 10, 15].find(function(value, index, arr) {  
    return value > 9;  
}) // 10  

In the above code, the callback function of the find method can accept three parameters, in turn, the current value, the current position, and the original array. The findIndex method for array instances is very similar to the find method, returning the location of the first eligible array member and -1 if all members do not meet the criteria.

[1, 5, 10, 15].findIndex(function(value, index, arr) {  
    return value > 9;  
}) // 2  

Both methods accept the second argument, which binds the this object of the callback function.

In addition, both methods can find NaN, making up for the shortcomings of the array's IndexOf method.

[NaN].indexOf(NaN)  
// -1  
[NaN].findIndex(y => Object.is(NaN, y))  
// 0  

fill()

The fill() method populates an array with a given value.

['a', 'b', 'c'].fill(7)  
// [7, 7, 7]  
new Array(3).fill(7)  
// [7, 7, 7]  
['a', 'b', 'c'].fill(7, 1, 2)  
// ['a', 7, 'c']  

The above code shows that the fill method is very convenient for the initialization of empty arrays. Elements that are already in the array are erased altogether.

The fill() method can also accept the second and third parameters, which specify the start and end positions of the fill

['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']

entries(), keys() and values()

ES6 provides three new methods -- entries(), keys(), and values() -- for traversing arrays. T hey all return a traverser object that can be used with for... The only difference between of loops is that keys() are traversals of key names, values() are traversals of key values, and entries() are traversals of key value pairs.

for (let index of ['a', 'b'].keys()) {  
    console.log(index);  
}  
// 0  
// 1  
for (let elem of ['a', 'b'].values()) {  
    console.log(elem);  
}  
// 'a'  
// 'b'  
for (let [index, elem] of ['a', 'b'].entries()) {  
    console.log(index, elem);  
}  
// 0 "a"  
// 1 "b"  

If you don't use for... of loop, you can manually call the next method of the traverser object for traversal.

let letter = ['a', 'b', 'c'];  
let entries = letter.entries();  
console.log(entries.next().value); // [0, 'a']  
console.log(entries.next().value); // [1, 'b']  
console.log(entries.next().value); // [2, 'c']  

includes()

In ES5, we often use the array's indexOf method to check if a value is included. T he indexOf method has two disadvantages, one is not semantic enough, its meaning is to find the first occurrence of parameter values, so to compare whether it is not equal to -1, not intuitive enough to express. Second, it is judged internally using a strictly equivalent operator , which can lead to misjudgment of NaN.

[NaN].indexOf(NaN)  
// -1  
includes使用的是不一样的判断算法,就没有这个问题。  
[NaN].includes(NaN)  
// true 

The Array.prototype.includes method returns a Boolean value that indicates whether an array contains a given value, similar to the string's includes method. This method belongs to ES7, but is supported by the Babel transcoder.

[1, 2, 3].includes(2); // true  
[1, 2, 3].includes(4); // false  
[1, 2, NaN].includes(NaN); // true 

The second argument of the method represents the starting position of the search, which defaults to 0. If the second argument is negative, it represents the position of the countdown, and if it is larger than the array length (for example, the second argument is -4, but the array length is 3), it is reset to start at 0.

[1, 2, 3].includes(3, 3); // false  
[1, 2, 3].includes(3, -1); // true  

The following code is used to check whether the current environment supports this approach and, if not, to deploy a simple alternative version.

const contains = (() =>  
Array.prototype.includes  
    ? (arr, value) => arr.includes(value)  
    : (arr, value) => arr.some(el => el === value)  
)();  


contains(["foo", "bar"], "baz"); // => false  

In addition, map and Set data structures have a has method that requires attention to distinguish them from includes.

The has method of map structure is used to find key names such as Map.prototype.has (key), WeakMap.prototype.has (key), Reflect.has (target, propertyKey).

The has method of the Set structure is used to find values such as Set.prototype.has (value), WeakSet.prototype.has .has.).

The empty bit of the array

An empty bit in an array means that there is no value at one location in the array. For example, arrays returned by array constructors are empty.

Note that the empty space is not undefined, and the value of one position is equal to the underfined and is still valuable. The empty bit is without any value, as the in operator can explain.

0 in [undefined, undefined, undefined] // true
0 in [, , ,] // false

The code above shows that the number 0 position of the first array has a value, and the number 0 position of the second array has no value.

ES5's handling of empty spaces is already very inconsistent and, in most cases, is ignored.

  • ForEach(), filter(), every() and soome() all skip empty seats.
  • map() skips the empty seat, but retains this value
  • join() and toString() treat empty spaces as underfined, while underfined and null are processed as empty strings.

// forEach方法
[,'a'].forEach((x,i) => console.log(i)); // 1


// filter方法
['a',,'b'].filter(x => true) // ['a','b']


// every方法
[,'a'].every(x => x==='a') // true


// some方法
[,'a'].some(x => x !== 'a') // false


// map方法
[,'a'].map(x => 1) // [,1]


// join方法
[,'a',undefined,null].join('#') // "#a##"


// toString方法
[,'a',undefined,null].toString() // ",a,,"

ES6 explicitly converts empty seats to underfined.

//Array.from方法会将数组的空位,转为undefined,也就是说,这个方法不会忽略空位。  
Array.from(['a',,'b'])  // [ "a", undefined, "b" ]  


//扩展运算符(...)也会将空位转为undefined。  
[...['a',,'b']]  // [ "a", undefined, "b" ]  


//copyWithin()会连空位一起拷贝。  
[,'a','b',,].copyWithin(2,0) // [,"a",,"a"]  


//fill()会将空位视为正常的数组位置。  
new Array(3).fill('a') // ["a","a","a"]  


//for...of循环也会遍历空位。  
let arr = [, ,];  
for (let i of arr) {  
    console.log(1);  
}  
// 1  
// 1  
//上面代码中,数组arr有两个空位,for...of并没有忽略它们。如果改成map方法遍历,空位是会跳过的。  


//entries()、keys()、values()、find()和findIndex()会将空位处理成undefined。  
// entries()  
[...[,'a'].entries()] // [[0,undefined], [1,"a"]]  
// keys()  
[...[,'a'].keys()] // [0,1]  
// values()  
[...[,'a'].values()] // [undefined,"a"]  
// find()  
[,'a'].find(x => true) // undefined  
// findIndex()  
[,'a'].findIndex(x => true) // 0  
//由于空位的处理规则非常不统一,所以建议避免出现空位。

The article comes from the public number: Monkey Brother, front end, author: monkeysoft

The above is W3Cschool编程狮 about the relevant introduction, I hope to help you.