关于javascript:ES6

11次阅读

共计 16858 个字符,预计需要花费 43 分钟才能阅读完成。

let 与块级作用域

JS 中作用域有:全局作用域、函数作用域。没有块作用域的概念。ECMAScript 6(简称 ES6)中新增了块级作用域。
块作用域由 {} 包含,if 语句和 for 语句外面的 {} 也属于块作用域。

var elements = [{}, {}, {}];

for (var i=0; i < elements.length; i++) {elements[i].onclick = function() {console.log(i);
    }
}

elements[1].onclick();

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
3
3
3

通过闭包

var elements = [{}, {}, {}];

for (var i = 0; i < elements.length; i++) {elements[i].onclick = (function (i) {return function () {console.log(i);
        }
    })(i)
}

elements[0].onclick();
elements[1].onclick();
elements[2].onclick();

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
0
1
2

应用 let

var elements = [{}, {}, {}];

for (let i = 0; i < elements.length; i++) {elements[i].onclick = function () {console.log(i);
    }
}

elements[0].onclick();
elements[1].onclick();
elements[2].onclick();

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
0
1
2

数组的解构

const arr = [100,200,300];
const [a,b,c] = arr;
console.log(a,b,c);

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
100 200 300

只定义一个变量 须要 把其它地位空进去

const arr = [100,200,300];

const [,,c] = arr;

console.log(c);
////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
300

应用 … 定义剩下的变量

只能定义在最初的地位

const arr = [100,200,300];

const [a, ...rest] = arr;

console.log(rest);

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
[200, 300]
const arr = [100,200,300];

const [...rest] = arr;

console.log(rest);

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
[100, 200, 300]
const arr = [100,200,300];

const [...rest,c] = arr;

console.log(rest);

////
F:\ 拉钩前端 \lagou\task1\task1.js:15
const [...rest,c] = arr;
       ^^^^^^^

解构的时候赋初始值

const arr = [100, 200, 300];

const [a, b, c = 123, d = 'defaultValue'] = arr;

console.log(c, d);

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
300 defaultValue

解构实例:解析门路

// 传统写法
const path = '/foo/bar/baz';
const temp = path.split('/');
const rootdir = temp[1];
console.log(temp);
console.log(rootdir);

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
['','foo','bar','baz']
foo
// 解构写法
const path = '/foo/bar/baz';
const [,rootdir] = path.split('/');

console.log(rootdir);

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
foo

对象的解构

对象是通过 key,数组是通过下标

const obj = {name:'yangzhen' , age:24};

const {name , age , sex} = obj;

console.log(sex,name,age);

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
undefined yangzhen 24

不应用别名

const obj = {name:'yangzhen' , age:24};

const name = 'jack';

const {name , age , sex} = obj;

console.log(sex,name,age);

////
const {name , age , sex} = obj;
        ^
SyntaxError: Identifier 'name' has already been declared

应用别名 赋初始值

const obj = {name:'yangzhen' , age:24};

const name = 'jack';

const {name:myname , age , sex = 18} = obj;

console.log(sex,myname,age);

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
18 yangzhen 24

字符串的扩大办法


const {log} = console

const message = 'Error: foo is noe defined.'

log (message.startsWith('Error'),
    message.endsWith('.'),
    message.includes('is')
)

////
true true true

函数参数的默认值

原始办法(对于布尔类型)

// 函数参数的默认值
function foo(enable) {// 原始办法(对于布尔类型)
    enable = enable === undefined ? true : false
    console.log(enable)
}

foo() //// true
foo(false) //// false

原始办法(对于其它类型)

// 函数参数的默认值
function foo(enable) {
    // 原始办法
    enable =  enable || 0
    console.log(enable)
}

foo()  //// 0
foo(5) //// 5

ES6 语法

function foo(enable = true){console.log(enable)
}

foo() //// true
foo(false) //// false

残余参数

形式一:应用 arguments

function foo(){console.log(arguments)
}

foo(1,2,3,4)
////
PS E:\lagou 前端 \demo> node .\part1\test1.js
[Arguments] {'0': 1, '1': 2, '2': 3, '3': 4}
function foo(){const [a,b,c,d] = arguments
    console.log(a,b,c,d)
}

foo('a',2,3,4)

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
a 2 3 4

形式二:应用 …

…args 放在最初 只能应用一次

function foo(first,...args){console.log(first)
    console.log(args)
}

foo('a',2,3,4)

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
a
[2, 3, 4]

···开展数组

const arr = [1,2,3,4]

console.log(...arr)

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
1 2 3 4

箭头函数与 this

一般函数:this 的指向在函数创立的时候是决定不了的,在调用的时候能力决定,谁调用的就指向谁,肯定要搞清楚这个。

箭头函数没有 prototype(原型),所以箭头函数自身没有 this。箭头函数外部的 this 是词法作用域,由上下文确定,this 指向在定义的时候继承自外层第一个一般函数的 this。函数体内的 this 对象,就是定义时所在的对象,与应用时所在的对象无关。

const name = 'jack'

const person = {
    name: 'tom',
    sayHi: function(){console.log(`my name is ${this.name}`)
    }
}

person.sayHi()

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
my name is tom
const name = 'jack'

const person = {
    name: 'tom',
    sayHi: function(){console.log(`my name is ${name}`)
    }
}

person.sayHi()

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
my name is jack

应用箭头函数

箭头函数不会扭转 this 的指向

const name = 'jack' //// 这个 name 并不是 this.name

const person = {
    name: 'tom',
    sayHi: () => {console.log(`my name is ${this.name}`)
    }
}

person.sayHi()

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
my name is undefined
const name = 'jack'

const person = {
    name: 'tom',
    sayHi: () => {console.log(`my name is ${name}`)
    }
}
console.log(this)
console.log(this.name)
person.sayHi()

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
{}
undefined
my name is jack

传统形式_this 的应用

const person = {
    name: 'tom',
    sayHi: function() {console.log(`my name is ${this.name}`)
    },
    sayHiAsync:function(){setTimeout(function () {console.log(`my name is ${this.name}`)
        }, 1000);
    }
}
person.sayHi()
person.sayHiAsync()

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
my name is tom
my name is undefined
const person = {
    name: 'tom',
    sayHi: function() {console.log(`my name is ${this.name}`)
    },
    sayHiAsync:function(){
        _this = this;
        setTimeout(function () {console.log(`my name is ${_this.name}`)
        }, 1000);
    }
}
person.sayHi()
person.sayHiAsync()

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
my name is tom
my name is tom

setTimeout 应用箭头函数 能够防止_this

箭头函数外部的 this 是词法作用域,由上下文确定

const person = {
    name: 'tom',
    sayHi: () => {console.log(`my name is ${this.name}`)
    },
    sayHiAsync:function(){setTimeout(()=> {console.log(`my name is ${this.name}`)
        }, 1000);
    }
}
person.sayHi()
person.sayHiAsync()

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
my name is undefined
my name is tom

对象字面量加强

const bar = '345'

const obj = {
    foo: 123,
    //bar:bar
    bar,
    //method1:function(){//  console.log(this)
    //}
    method1(){console.log(this)
    },
    [Math.random()]:456 // 能够间接减少
}

// 在传统办法中,对象动静的减少属性 
obj[Math.random()] = 123

console.log(obj)
obj.method1()

////

PS E:\lagou 前端 \demo> node .\part1\test1.js
{
  foo: 123,
  bar: '345',
  method1: [Function: method1],
  '0.8616180359346404': 123
}
{
  foo: 123,
  bar: '345',
  method1: [Function: method1],
  '0.8616180359346404': 123
}

对象扩大办法

Object.assign 将多个源对象中的属性复制到指标对象


const source1 = {
    a:123,
    b:123
}

const source2 = {
    b:789,
    d:789
}

const target = {
    a:456,
    c:456
}

const result =  Object.assign(target,source1,source2)

console.log(target)
console.log(result === target)

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
{a: 123, c: 456, b: 789, d: 789}
true

案例

function func(obj){

    obj.name = 'func obj'
    console.log(obj)
}

const obj = {name: 'global obj'}

func(obj)
console.log(obj)

////
{name: 'func obj'}
{name: 'func obj'}
function func(obj){const funObj = Object.assign({},obj)
    funObj.name = 'func obj'
    console.log(funObj)
}

const obj = {name: 'global obj'}

func(obj)
console.log(obj)

////
{name: 'func obj'}
{name: 'global obj'}

Proxy 代理对象

const person = {
    name: 'yang',
    age: 18
}
// 参数 1: 代理对象
// 参数 2: 代理的解决对象
const personProxy = new Proxy(person,{

    // 通过 get 办法去监督属性拜访
    // 参数 1: 所代理的指标对象
    // 参数 2: 内部所拜访的属性名
    get(target,property){console.log(target,property)

        return 100
    },
    // 通过 set 办法去实现属性设置
    set(){}
})

console.log(personProxy.name)

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
{name: 'yang', age: 18} name
100
const person = {
    name: 'yang',
    age: 18
}
// 参数 1: 代理对象
// 参数 2: 代理的解决对象
const personProxy = new Proxy(person,{

    // 通过 get 办法去监督属性拜访
    // 参数 1: 所代理的指标对象
    // 参数 2: 内部所拜访的属性名
    get(target,property){return property in target ? target[property] : 'default'
    },
    // 通过 set 办法去实现属性设置
    set(){}
})

console.log(personProxy.name)
console.log(personProxy.xxxx)

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
yang
default
const person = {
    name: 'yang',
    age: 18
}
// 参数 1: 代理对象
// 参数 2: 代理的解决对象
const personProxy = new Proxy(person,{

    // 通过 get 办法去监督属性拜访
    // 参数 1: 所代理的指标对象
    // 参数 2: 内部所拜访的属性名
    get(target,property){return property in target ? target[property] : 'default'
    },
    // 通过 set 办法去实现属性设置
    //1. 所代理的指标对象
    //2. 要写入的属性名
    //3. 要写入的值
    set(target,property,value){if(property === 'age') {if (!Number.isInteger(value)) {throw new TypeError(`${value} is not an int`)
            }
        }
        target[property] = value
    }
})

personProxy.age = 30
personProxy.sex = 'man'

console.log(personProxy)

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
{name: 'yang', age: 30, sex: 'man'}

proxy 和 Object.defineProperty()

Object.defineProperty()只能监听对象的读写

proxy 还能够有更多的操作

const person = {
    name: 'yang',
    age: 18
}

const personProxy = new Proxy(person,{deleteProperty(target,property){console.log('delete',property)
        delete target[property]
    }
})

delete personProxy.age

console.log(person)

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
delete age
{name: 'yang'}

proxy 更好的反对数组对象的监督

const list = []

const listProxy = new Proxy(list,{set(target,property,value) {console.log('set',property,value)
        target[property] = value
        return true // 示意设置胜利, 不写会报错
    }
})

listProxy.push(100)
listProxy.push(200)
console.log('list',list)

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
set 0 100
set length 1
set 1 200
set length 2
list [100, 200]

Reflect 对立的对象操作 API

动态类,封装了一系列对对象的底层操作

Reflet 成员办法就是Proxy 解决对象的默认实现

去掉 Reflect

const person = {
    name: 'yang',
    age: 18
}

const personProxy = new Proxy(person,{get(target,property) {console.log('watch logic')
       // return Reflect.get(target,property)
    }
})

console.log(personProxy.age)

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
watch logic
undefined

增加 Reflect

const person = {
    name: 'yang',
    age: 18
}

const personProxy = new Proxy(person,{get(target,property) {console.log('watch logic')
        return Reflect.get(target,property)
    }
})

console.log(personProxy.age)
////
PS E:\lagou 前端 \demo> node .\part1\test1.js
watch logic
18

Reflect 的作用:对立的提供一套用于操作对象的 API

不应用 Reflect 对对象的操作

const person = {
    name: 'yang',
    age: 18
}

// 判断 对象是否有 属性
console.log('name' in person)
// 获取对象所有的 Key
console.log(Object.keys(person))
// 删除对象的属性
console.log(delete person['age'])

console.log(person)

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
true
['name', 'age']
true
{name: 'yang'}

应用 Reflect 对对象的操作

const person = {
    name: 'yang',
    age: 18
}

// 判断 对象是否有 属性
console.log(Reflect.has(person,'name'))
// 获取对象所有的 Key
console.log(Reflect.ownKeys(person))
// 删除对象的属性
console.log(Reflect.deleteProperty(person,'age'))

console.log(person)

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
true
['name', 'age']
true
{name: 'yang'}

Promise 一种更优的异步编程解决方案

解决了传统异步编程中函数嵌套过深的问题

class 关键字

传统应用 prototype

function Person (name) {this.name = name;}

Person.prototype.say = function () {console.log(`my name is ${this.name}`)
}

const p = new Person('tom')

p.say()

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
my name is tom

应用 class

class Person {constructor(name) {this.name = name}

    say() {console.log(`my name is ${this.name}`)
    }
}


const p = new Person('tom')

p.say()

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
my name is tom

静态方法

class Person {constructor(name) {this.name = name}

    say() {console.log(`my name is ${this.name}`)
    }

    static create(name) {return new Person(name)
    }
}


const p = Person.create('tom')

p.say()

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
my name is tom

继承

class Person {constructor(name) {this.name = name}

    say() {console.log(`my name is ${this.name}`)
    }

    static create(name) {return new Person(name)
    }
}

class Student extends Person {constructor(name,number) {super(name)
        this.number = number
    }

    hello() {super.say()
        console.log(`my number is ${this.number}`)
    }
}

const s = new Student('jack',100)

s.hello()

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
my name is jack
my number is 100

Set 数据类型

const s = new Set()

//add 返回的是 Set 所以能够链式调用
s.add(1).add(2).add(3).add(4).add(4).add(5)

//set 元素 没有反复 所以 主动去重
console.log(s) //// Set {1, 2, 3, 4, 5}

//Set 的遍历
s.forEach(i => {console.log(i) //// 1 2 3 4 5 
})

//Set 的罕用办法
console.log(s.size) //// 5
console.log(s.has(100)) ////false
console.log(s.delete(3)) ////true
console.log(s) //// Set {1, 2, 4, 5}

Set 对 数组的去重解决

Array.from() 能够将 Set 转化为 Array


const arr = [1,2,3,1,2,1,4,1]

//const result = Array.from(new Set(arr))

const result = [...new Set(arr)]

console.log(result)

PS E:\lagou 前端 \demo> node .\part1\test1.js
[1, 2, 3, 4]

Map 数据结构

一般键值对

对象的 key 只能是 String 类型,不是 String 类型会被主动转化为 String

const obj = {}

obj[true] = 'value'
obj[123] = 'value'
obj[{a: 1}] = 'value'

console.log(Object.keys(obj))

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
['123', 'true', '[object Object]' ]

Map 类型

const m = new Map()
const tom = {name:'tom'}
m.set(tom,90)

console.log(m)
console.log(m.get(tom))

//Map 的遍历
m.forEach((value,key)=>{console.log(value,key)
})

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
Map {{ name: 'tom'} => 90 }
90
90 {name: 'tom'}

Symbol 新的数据类型

最次要的作用就是为对象增加 举世无双 的属性名

const  s = Symbol()

console.log(s)
console.log(typeof s)
console.log(Symbol() === Symbol())
// 增加形容文本
// 留神:即便增加同一形容文本 Symbol 也是不一样的
console.log(Symbol('foo'))

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
Symbol()
symbol
false 
Symbol(foo)

设置对象公有成员

const name = Symbol();
const person = {[name]:'yang',
    say(){console.log(this[name])
    }
}

console.log(person[Symbol()])
person.say()

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
undefined
yang

for of 循环

是一种数据对立的遍历形式

const arr = [100,200,300,400,500]

for (item of arr) {console.log(item) ////100 200 300 400
    if(item > 300){break}
}

// 不能跳出循环
arr.forEach(item =>{console.log(item) ////100 200 300 400 
})

//some() 办法用于检测数组中的元素是否满足指定条件(函数提供)。//some() 办法会顺次执行数组的每个元素:// 如果有一个元素满足条件,则表达式返回 true , 残余的元素不会再执行检测。// 如果没有满足条件的元素,则返回 false。//every() 办法用于检测数组所有元素是否都合乎指定条件(通过函数提供)。//every() 办法应用指定函数检测数组中的所有元素:// 如果数组中检测到有一个元素不满足,则整个表达式返回 false,且残余的元素不会再进行检测。// 如果所有元素都满足条件,则返回 true。const result =  arr.some((item)=>{return item > 300})

console.log(result) ////true

for (i in arr) {console.log(arr[i]) ////100 200 300 400 500
}

Set 的 for of 遍历

const s =  new Set(['foo','bar'])

for (const item of s) {console.log(item)
}

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
foo
bar

Map 的 for of 遍历

const m = new Map()

m.set('foo','123')
m.set('bar','456')

for(const item of m) {console.log(item)
}

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
['foo', '123']
['bar', '456']

应用数组的解构失去 K V

const m = new Map()

m.set('foo','123')
m.set('bar','456')

for(const [key,value] of m ) {console.log(key,value)
}

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
foo 123
bar 456

实现可迭代接口 Iterable

对象是不能够间接迭代的

在对象中挂一个 iterator 办法,在这个办法中返回一个迭代器对象

接口约定:外部必须要有一个用于迭代的 next 办法

const obj = {store: ['foo','bar','baz'],
    [Symbol.iterator]: function() {
        let index = 0
        const self = this
        return {next: function() {
                const result = {value:self.store[index],
                    done:index >= self.store.length
                }
                index++
                return result
            }
        }
    }
}

for (const item of obj) {console.log('循环',item)
}

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
循环 foo
循环 bar
循环 baz

迭代器模式

实现迭代器的目标

场景:协同开发一个工作清单利用

//============== 我的代码 ==============
const todos= {life:['吃饭','睡觉','打豆豆'],
   learn:['语言','数学','英语'],
   
}

//============== 你的代码 ==============
for(const item of todos.life){console.log(item)
}

for(const item of todos.learn){console.log(item)
}

如果我须要在我的 todos 数据列表里增加数据时,你的代码就须要作出相应的更改,对于调用来说,代码耦合度太高

 //============== 我的代码 ==============
const todos= {life:['吃饭','睡觉','打豆豆'],
  learn:['语言','数学','英语'],
  work:['唱歌']
}

//============== 你的代码 ==============
for(const item of todos.life){console.log(item)
}

for(const item of todos.learn){console.log(item)
}

for(const item of todos.work){console.log(item)
}
 

如何解决:

如果我的代码可能对外对立提供一个遍历的接口

对于调用者而已,就不必去关怀它外部的数据结构,也不必放心构造的扭转

咱们能够本人写一个办法来实现:

//============== 我的代码 ==============
const todos = {life: ['吃饭', '睡觉', '打豆豆'],
    learn: ['语言', '数学', '英语'],
    work: ['唱歌'],
    each: function (callback) {const all = [].concat(this.life, this.learn, this.work)
        for (item of all) {callback(item)
        }
    }
}

//============== 你的代码 ==============
todos.each(function (item) {console.log(item);
})

用迭代器的办法实现

//============== 我的代码 ==============
const todos = {life: ['吃饭', '睡觉', '打豆豆'],
    learn: ['语言', '数学', '英语'],
    work: ['唱歌'],
    [Symbol.iterator]:function() {// 应用对象开展符 等同于 [].concat
        const all = [...this.life,...this.learn,...this.work]
        let index = 0
        return{next:function(){
                return{value:all[index],
                    done: index++ >= all.length //true 就迭代实现了
                }
            }
        }
    }
}

//============== 你的代码 ==============
for(item of todos) {console.log(item)
}

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
吃饭
睡觉
打豆豆
语言
数学
英语
唱歌

迭代器的外围 就是对外提供对立遍历接口,让内部不必去放心外部的数据结构是怎么样的

这里展现的 each 办法只实用于这里展现的数组构造

而 ES2015 种的迭代器 是从语言层面去实现的迭代器模式,所以说它实用于任何数据结构,只有实现了 iterable 接口,那咱们就能够实现应用 for…of 遍历对象

生成器函数

解决异步编程回调嵌套过深所导致的问题

function * foo(){console.log('test')
    return 100
}

const result = foo()
console.log(result)
console.log(result.next())

////
Object [Generator] {}
test
{value: 100, done: true}

惰性执行

yield

function * foo(){console.log('111')
    yield 100
    console.log('222')
    yield 200
    console.log('333')
    yield 300
}

const generator = foo()
console.log(generator)
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())

////
Object [Generator] {}
111
{value: 100, done: false}
222
{value: 200, done: false}
333
{value: 300, done: false}
{value: undefined, done: true}

Generator 利用

案例一:发号器

function * createIdMaker(){
    let id = 1
    while(true) {yield id++}
}

const idMaker = createIdMaker()
console.log(idMaker.next().value)
console.log(idMaker.next().value)
console.log(idMaker.next().value)
console.log(idMaker.next().value)

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
1
2
3
4

案例二:应用 Generator 函数实现 Iterator 办法

const todos = {life: ['吃饭', '睡觉', '打豆豆'],
    learn: ['语言', '数学', '英语'],
    work: ['唱歌'],
    [Symbol.iterator]: function* () {const all = [...this.life, ...this.learn, ...this.work]
        for (item of all) {yield item}
    }
}

for (const item of todos) {console.log(item)
}

////
PS E:\lagou 前端 \demo> node .\part1\test1.js
吃饭
睡觉
打豆豆
语言
数学
英语
唱歌

ES2016

Array.prototype.includes

咱们先看看 indexOf 办法

const arr = ['foo',1,NaN,false]

console.log(arr.indexOf('foo'))
console.log(arr.indexOf(1))
console.log(arr.indexOf(NaN))
console.log(arr.indexOf(false))

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
0
1
-1
3

indexOf 无奈查看出 NaN

NaN 是一个非凡的数字值(typeof NaN 的后果为 number),是 not a number 的缩写,示意不是一个非法的数字。
留神点:NaN 是惟一一个和本身不相等的值:NaN === NaN // false

includes 能够查看出 NaN 返回布尔值

const arr = ['foo',1,NaN,false]

console.log(arr.includes('foo'))
console.log(arr.includes(1))
console.log(arr.includes(NaN))
console.log(arr.includes(false))

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
true
true
true
true

指数运算符

console.log(Math.pow(2,10))
console.log(2 ** 10)

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
1024
1024

ES2017

Object.values

const obj = {
    foo: 'value1',
    bar: 'balue2'
}

console.log(Object.values(obj))

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
['value1', 'balue2']

Object.entries

数组模式返回键值对

const obj = {
    foo: 'value1',
    bar: 'balue2'
}

console.log(Object.entries(obj))

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
[[ 'foo', 'value1'], ['bar', 'balue2'] ]

因而能够应用 for of

const obj = {
    foo: 'value1',
    bar: 'balue2'
}

for (const [key, value] of Object.entries(obj)) {console.log(key, value)
}

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
foo value1
bar balue2

应用 entries 转化 Map 对象

const obj = {
    foo: 'value1',
    bar: 'balue2'
}

console.log(new Map(Object.entries(obj)))

////
PS F:\ 拉钩前端 \lagou> node .\task1\task1.js
Map {'foo' => 'value1', 'bar' => 'balue2'}
正文完
 0