ES6重要且最全知识点(上)

目录

一、let命令

二、块级作用域

     三、关于变量提升

        四、顶层对象组合

五、global This对象

      六、模式匹配

七、对象的结构赋值

不能使用圆括号:

应用

八、模板字符串

九、正则表达式

方法:match,replace,search,split

u修饰符(以下六种情况都要加/u)

十、数值的扩展

Number()、parseInt()、parseFloat()

Number.isFinite()和Number.isNaN()

Number.isInteger()用来判断一个数值是否为整数。(不建议用)

math对象的扩展:17个方法

十一、BigInt数据类型

十二、函数的扩展

作用域:

rest参数

严格模式: 'use strict'

箭头函数:简化回调函数

         作用:封装回调函数

尾调用:

尾递归:

函数柯里化:

 十三、数组

       扩展运算符(...)

复制数组

 合并数组

Map 和 Set 结构,Generator 函数

 Array.from()

 includes()方法:返回一个布尔值,表示某个数组是否包含给定的值

at()

拷贝数组:不影响原来的

 空位:ES6 则是明确将空位转为undefined

 十四、对象

扩展运算符

解构赋值

 属性的遍历:

Object.is()

十五、symbol对象

 十六、Map结构


一、let命令

  • 只在代码块里有效,在代码块外调用会报错(const也一样)

  • 同一个作用域不可使用 let 重复声明同一个变量(for循环变量是父作用域,循环体内部为单独的子作用域)(const也一样)

  • es6规定,只要块级作用域内存在 let,const 命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响凡是在声明之前就使用这些变量,就会报错(暂时性死区!!!)(const也一样)

  • const命令必须初始化,且变量不能改

    {
        let a = 10;
        let b = 1;
    }
    a;//a is not defined
    b;//1
    
    // 第一种写法,报错
    if (true) let x = 1;   
    ---应该改成以下----否则加
    let x = 1;  
    if (true){}
    
    // 第二种写法,不报错
    if (true) {
      let x = 1;
    }

    二、块级作用域

  • ES6 允许块级作用域的任意嵌套。
  • ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。

     三、关于变量提升

  • 只有声明本身会被提升,而赋值操作不会被提升。
  • 变量会提升到其所在函数的最上面,而不是整个程序的最上面。
  • 函数声明会被提升,但函数表达式不会被提升。
  • 函数声明的优先级高于普通变量申明的优先级,并且函数声明和函数定义的部分一起被提升。
  • 同一个变量只会声明一次,其他的会被忽略掉。

        四、顶层对象组合

  • 在浏览器环境指的是window对象,在 Node 指的是global对象。
    var a = 1;
    // 如果在 Node 的 REPL 环境,可以写成 global.a
    // 或者采用通用方法,写成 this.a
    window.a // 1
    let b = 1;
    window.b // undefined

    五、global This对象

  • 浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。
  • 浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。
  • Node 里面,顶层对象是global,但其他环境都不支持。
  • 基于以上这么乱,所以采用this,this会返回顶层对象。但是,Node.js 模块中this返回的是当前模块,ES6 模块中this返回的是undefined。 最后用globalThis解决。

      六、模式匹配

  • 如果解构不成功,变量的值就等于undefined。
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3

let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []

// 报错
let [foo] = 1;
let [foo] = false;

//解构赋值指定默认值
let [foo = true] = [];
foo // true

let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'

!!!注意
let [x = 1] = [undefined];//只有值为undefined,默认值失效。
x // 1
let [x = 1] = [null];
x // null

function f() {
  console.log('aaa');
}
let [x = f()] = [1];//x已经赋值,f()不会用到

        总结:函数可以使用默认值,也可以使用被赋值,只有赋值的数是undefined的时候,默认值才可以生效,不然被赋值为优先。

七、对象的结构赋值

  • 对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
  • 解构失败为undefined
------嵌套结构--------
let obj = {
  p: [
    'Hello',
    { y: 'World' }
  ]
};

let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"
//注意,这时p是模式,不是变量,因此不会被赋值。

//如果p也要作为变量赋值,可以写成下面这样。
let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]
-----------------------------------
let obj = {};
let arr = [];
({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });
obj // {prop:123}
arr // [true]
//如果父属性不存在则会报错

注意点:圆括号解构:
// 正确的写法
let x;
({x} = {x: 1});
-------------------------数组解构
let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3
---------------字符串解构
----------------数值和布尔值解构:解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
let {toString: s} = 123;
s === Number.prototype.toString // true

  • 不能使用圆括号:

1.变量声明

2.函数参数

3.赋值语句的模式

  • 应用

1.交换变量
2.从函数返回多个值
// 返回一个数组
function example() {
  return [1, 2, 3];
}
let [a, b, c] = example();
// 返回一个对象
function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();
--------------------------------
3.函数参数的定义
// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});

4.提取json数据!!!!!
let jsonData = {
  id: 42,
  status: "OK",
  data: [867, 5309]
};

let { id, status, data: number } = jsonData;

console.log(id, status, number);
// 42, "OK", [867, 5309]

5.函数参数的默认值
6.遍历map解构
const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');

for (let [key, value] of map) {
  console.log(key + " is " + value);
}
// first is hello
// second is world

7.输入模块的指定方法

八、模板字符串

  • 模板字符串(template string)是增强版的字符串,用反引号(`)标识。
// 字符串中嵌入变量
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
//调用函数
`foo ${fn()} bar`

九、正则表达式

  • 方法:match,replace,search,split

String.prototype.match 调用 RegExp.prototype[Symbol.match]

String.prototype.replace 调用 RegExp.prototype[Symbol.replace]

String.prototype.search 调用 RegExp.prototype[Symbol.search]

String.prototype.split 调用 RegExp.prototype[Symbol.split]

var regex = new RegExp('xyz', 'i');
// 等价于
var regex = /xyz/i;

  • u修饰符(以下六种情况都要加/u)

1.点字符 2.unicode字符 3.量词 4.预定义模式 5.i修饰符 6.转义

十、数值的扩展

  • ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O)表示。

如果要0b,0o前缀的字符串数值转为十进制,要使用Number方法。

Number('0b111')  // 7
Number('0o10')  // 8
  • 数值分隔(_)三位数字一个

注意:科学计数法里面,表示指数的e或E和小数点前后不能有分隔符,

  • Number()、parseInt()、parseFloat()

  • Number.isFinite()和Number.isNaN()

注意,如果参数类型不是数值,Number.isFinite一律返回false。

如果参数类型不是NaN,Number.isNaN一律返回false。

  • Number.isInteger()用来判断一个数值是否为整数。(不建议用)

Number.isInteger(25) // true
Number.isInteger(25.0) // true
Number.isInteger(3.0000000000000002) // true
  • math对象的扩展:17个方法

1.Math.trunc方法用于去除一个数的小数部分,返回整数部分。

2.Math.sign方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数 值。

十一、BigInt数据类型

  • BigInt 只用来表示整数,没有位数的限制,任何位数的整数都可以精确表示。
  • 为了与 Number 类型区别,BigInt 类型的数据必须添加后缀n。
1234 // 普通整数
1234n // BigInt
42n === 42 // false
typeof 123n // 'bigint'
//BigInt 可以使用负号(-),但是不能使用正号(+)

  • JavaScript 原生提供BigInt函数,将其他类型的值转为 BigInt。
BigInt('123') // 123n
BigInt(false) // 0n
new BigInt() // TypeError
BigInt(undefined) //TypeError
BigInt(null) // TypeError
BigInt('123n') // SyntaxError
BigInt(1.5) // RangeError

        转换:可以使用Boolean()、Number()和String()这三个方法,将 BigInt 可以转为布尔值、数值和字符串类型

十二、函数的扩展

  • 参数变量是默认声明的,所以不能用let或const再次声明。
  • 参数默认值是不断计算的
let x = 99;
function foo(p = x + 1) {//每调用foo(),会重新计算x+1
  console.log(p);
}
foo() // 100

  • catch命令参数省略
try {// ...} catch {// ...}
  • 函数的length属性
(function (a) {}).length // 1,指定没有默认值的参数个数
(function (a = 5) {}).length // 0

  • 作用域:

        一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。

        函数外部用var声明的变量和函数内部不声明就赋值的变量均为全局变量可在全局使用

        函数内部声明的变量都是局部变量,用var也是一样,只在函数内部有效。

var x = 1;
function f(x, y = x) {
  console.log(y);
}
f(2) // 2,默认值x指向第一个参数x,而不是全局变量x,是2
------------------------------------------------------------------
let x = 1;//全局变量x不存在,去掉就会报错
function f(y = x) {
  let x = 2;
  console.log(y);
}
f() // 1,参数y = x形成一个单独的作用域。这个作用域里面,变量x本身没有定义,所以指向外层的全局变量x。
//函数体内部的局部变量x影响不到默认值变量x。
----------------------------------------------------------------------
var x = 1;
function foo(x, y = function() { x = 2; }) {
  var x = 3;
  y();
  console.log(x);
}
foo() // 3
x // 1

var x = 1;
function foo(x, y = function() { x = 2; }) {
  var x;
  x = 3;
  y = function() {
   var x ;
   x = 2;
  }
  console.log(x);
}
foo() // 3
x // 1

  • rest参数

        rest参数可以代替arguments方法,arguments是伪书组需要Array.from(arguments)转为数组,而rest就是一个真正的数组

// arguments变量的写法
function sortNumbers() {
  return Array.from(arguments).sort();
}
// rest参数的写法
const sortNumbers = (...numbers) => numbers.sort();

  • 严格模式: 'use strict'

        规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。

  • 箭头函数:简化回调函数

        箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。

        如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。

let getTempItem = id => ({ id: id, name: "Temp" });

         箭头函数可以与变量解构结合使用。

const full = ({ first, last }) => first + ' ' + last;
// 等同于
function full(person) {
  return person.first + ' ' + person.last;
}

         1.箭头函数没有自己的this,内部的this就是定义时上层作用域中的this(且this指向是固定的)

function Timer() {
  this.s1 = 0;
  this.s2 = 0;
  // 箭头函数
  setInterval(() => this.s1++, 1000);
  // 普通函数
  setInterval(function () {
    this.s2++;
  }, 1000);
}
var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0

         作用:封装回调函数

function foo() {
  return () => {
    return () => {
      return () => {
        console.log('id:', this.id);
      };
    };
  };
}
var f = foo.call({id: 1});
var t1 = f.call({id: 2})()(); // id: 1
var t2 = f().call({id: 3})(); // id: 1
var t3 = f()().call({id: 4}); // id: 1
//箭头函数没有自己的this,怎么嵌套都是指向foo的this,只有一个

        2.不可以当作构造函数,也就是说,不可以对箭头函数使用new命令,否则会抛出一个错误。

        3.不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

        4.不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

  • 尾调用:

  • 某个函数的最后一步是调用另一个函数,也就是函数最后一步操作调用

    function f(x){
      return g(x);
    }
  • 尾递归:

  • 不会发生“栈溢出”错误。
  •  

    !!!比较著名的例子,就是计算 Fibonacci 数列,

    应用:改写递归函数,确保最后一步只调用自身。做到这一点的方法,就是把所有用到的内部变量改写成函数的参数。

  • 函数柯里化:

  • 将多参数的函数转换成单参数的形式。这里也可以使用柯里化。

 十三、数组

  •        扩展运算符(...)

        array.push(...items)和add(...numbers):将数组变为参数序列

...[1,2,3] === (1,2,3)
//作用:替代apply()方法

  • 复制数组

1.直接复制,是复制指向的指针,改变该数组会影响原来的数组,

//用concat
const a2 = a1.concat();
//用扩展运算符
const a2 = [...a1];

  •  合并数组

//浅拷贝
const a1 = [{ foo: 1 }];
const a2 = [{ bar: 2 }];
const a3 = a1.concat(a2);
const a4 = [...a1, ...a2];

         解构赋值:

        将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。

const [first, ...rest] = [];
first // undefined
rest  // []
const [...butLast, last] = [1, 2, 3, 4, 5];
// 报错

         querySelectorAll()方法返回的是一个NodeList对象。它不是数组,而是一个类似数组的对象。

  • Map 和 Set 结构,Generator 函数

1.Generator 函数运行后,返回一个遍历器对象,

const go = function*(){
  yield 1;
  yield 2;
  yield 3;
};
[...go()] // [1, 2, 3]
  •  Array.from()

// NodeList 对象
let ps = document.querySelectorAll('p');
Array.from(ps).filter(p => {
  return p.textContent.length > 100;
});

// arguments 对象
function foo() {
  var args = Array.from(arguments);
  // ...
}

Array.from()方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map) 

        !!!在ES6中,有三类数据结构原生具备Iterator接口:数组、某些类似数组的对象、Set和Map结构,字符串。

Iterator(遍历器)具有next方法,具有return方法和throw方法。

对象没有,需要部署遍历器接口(Symbol.iterator)

  • entries()、keys()、values():用于遍历数组

    区别:keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。

  • find()、findIndex(),findLast(),findLastIndex():找出第一个符合条件的数组成员。
[1, 5, 10, 15].find(function(value, index, arr) {
  return value > 9;
}) // 10
find()方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。

findIndex()方法的用法与find()方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。

findLast()和findLastIndex(),从数组的最后一个成员开始,依次向前检查,其他都保持不变。

  • fill():用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去。第二个和第三个参数,用于指定填充的起始位置和结束位置。

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

//被赋值的是同一个内存地址的对象
let arr = new Array(3).fill({name: "Mike"});
arr[0].name = "Ben";
arr
// [{name: "Ben"}, {name: "Ben"}, {name: "Ben"}]

  •  includes()方法:返回一个布尔值,表示某个数组是否包含给定的值

该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。

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

         注意区分:Map 和 Set 数据结构有一个has方法,需要注意与includes区分。

        1.Map 结构的has方法,是用来查找键名的,比如Map.prototype.has(key)、

        2.Set 结构的has方法,是用来查找值的,比如Set.prototype.has(value)、

  • at()

        数组实例增加了at()方法,接受一个整数作为参数,返回对应位置的成员,并支持负索引。

const sentence = 'This is a sample sentence';
sentence.at(0); // 'T'
sentence.at(-1); // 'e'
sentence.at(-100) // undefined

  • 拷贝数组:不影响原来的

    toReversed()对应reverse(),用来颠倒数组成员的位置。

    toSorted()对应sort(),用来对数组成员排序。

    toSpliced()对应splice(),用来在指定位置,删除指定数量的成员,并插入新成员。

    with(index, value)对应splice(index, 1, value),用来将指定位置的成员替换为新的值。

  •  空位:ES6 则是明确将空位转为undefined

        1.forEach(), filter(), reduce(), every() 和some()都会跳过空位。

        2.map()会跳过空位,但会保留这个值

        3.join()和toString()会将空位视为undefined,而undefined和null会被处理成空字符串。

        4.fill()、entries()、keys()、values()、find()和findIndex()

 十四、对象

  • 扩展运算符

let foo = { ...['a', 'b', 'c'] };
foo
// {0: "a", 1: "b", 2: "c"}

  • 解构赋值

  • super关键字:指向当前对象的原型对象,只能用在对象的方法之中,用在其他地方都会报错。
  • 可枚举性
const proto = {
  foo: 'hello'
};
const obj = {
  foo: 'world',
  find() {return super.foo;}
};
Object.setPrototypeOf(obj, proto);
obj.find() // "hello"

  •  属性的遍历:

规则: 首先遍历所有数值键,按照数值升序排列。

其次遍历所有字符串键,按照加入时间升序排列。

最后遍历所有 Symbol 键,按照加入时间升序排列。

(1)for...in

for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。

(2)Object.keys(obj)

Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。

(3)Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。

(4)Object.getOwnPropertySymbols(obj)

Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。

(5)Reflect.ownKeys(obj)

Reflect.ownKeys返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。

  • Object.is()

        解决弊端:==(类型转换)===(NaN等于本身为false,+0与-0相等)

Object.is('foo', 'foo')
// true
Object.is({}, {})
// false

        Object.assign()方法:对象的合并

十五、symbol对象

        Symbol 值通过Symbol()函数生成

let s = Symbol();//s即为独一无二的值
typeof s
// "symbol"

 十六、Map结构

  • :本质上是键值对的集合(Hash 结构)

        1.Map.prototype.keys():返回键名的遍历器。

        Map.prototype.values():返回键值的遍历器。

        Map.prototype.entries():返回所有成员的遍历器。

        Map.prototype.forEach():遍历 Map 的所有成员。

2.扩展运算符

const map = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);

[...map.keys()]
// [1, 2, 3]
[...map.values()]
// ['one', 'two', 'three']
[...map.entries()]
// [[1,'one'], [2, 'two'], [3, 'three']]
[...map]
// [[1,'one'], [2, 'two'], [3, 'three']]

         3.结合数组的map方法、filter方法,可以实现 Map 的遍历和过滤(Map 本身没有map和filter方法

const map0 = new Map()
  .set(1, 'a')
  .set(2, 'b')
  .set(3, 'c');
const map1 = new Map(
  [...map0].filter(([k, v]) => k < 3)
);
// 产生 Map 结构 {1 => 'a', 2 => 'b'}
const map2 = new Map(
  [...map0].map(([k, v]) => [k * 2, '_' + v])
);
// 产生 Map 结构 {2 => '_a', 4 => '_b', 6 => '_c'}

const m = new Map();
const o = {p: 'Hello World'};

map.size // 1
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false

 注意,只有对同一个对象的引用,Map 结构才将其视为同一个键。这一点要非常小心。

本人是新手,如有错误请留言更正,谢谢各位小老师❀❀❀❀❀❀

参考~ECMAScript 6 入门

作者:阮一峰

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值