欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《ECMAScript 6 入门》笔记

程序员文章站 2022-07-16 20:02:31
...

1、babel-polyfill

Bable默认只转换新的javascript语法,而不转换新的API,比如iterator、gennerator、set、map、proxy、reflect、symbol、promise等全局对象。
举例来说,ES6在Array对象上新增了Array.from方法,babel就不会转换这个方法,需要通过bable-polyfill来进行转换

2、ESLint

用于静态检查代码的语法和风格

3、let

  • 用来声明变量,用法类似于var, 但是声明的变量,旨在let命令的代码块内有效。
var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6

  • 不存在变量提升

在var情况下,变量在声明之前使用,虽然值为undefined,但是不会报错,但是由于let不存在变量提升,因此会报错

// var 的情况
console.log(foo); // 输出undefined
var foo = 2;

// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;

  • 暂时性死区

只要块级作用域内存在let命令,他所声明的变量就绑定在这个区域,不受外部影响

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

  • 不允许重复声明
  • 块级作用域
{{{{
  {let insane = 'Hello World'}
  console.log(insane); // 报错
}}}};

  • 块级作用域与函数声明

在ES5中,函数只能在顶层作用域中声明,不能再块级作用域中声明,

const

  • const声明一个只读的常量,一旦声明,常量的值就不能改变。
  • const一旦声明,就必须立即初始化,不能六道以后复制,否则会报错。
  • 本质

const实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。

对于简单类型的数据(数值、字符串、布尔值),值就保存在指向的内存地址,因此等同于常量。

但对于复合类型的数据(主要是对象和数组),指向的只是一个指向实际数据的指针,const只能保证这个指针固定不懂,至于指向的数据结构是不是可变,就不能控制了

const foo = {};

// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123

// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only

若真的想将对象冻结,应该使用Object.freeze()

声明变量的六种方法

var function let const import class

顶层对象的属性

顶层对象,在浏览器环境指的是window对象,在node指的是global对象

ES5中,顶层对象和全局变量是等价的,而在ES6中,let、const、class声明的全局变量,不属于顶层对象的属性。

变量的结构赋值

从数组和对象中提取值,对变量进行赋值,被称之为解构。只要等号两边的模式相同,左边的变量就会被赋予对应的值。

let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3

let [ , , third] = ["foo", "bar", "baz"];
third // "baz"

let [x, , y] = [1, 2, 3];
x // 1
y // 3

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

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

只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值。

字符串的扩展

ES6为字符串添加了遍历器接口,是的字符可以被for …of 循环遍历

for(let codePoint of 'foo'){
    console.log(condePoint)
}
// f
// o
// o
includes(), startsWith(), endsWith()

传统上,只有indexOf方法可以用来判断一个字符串是否包含另一个字符串。es6提供了以下三种新方法

  • includes() :返回布尔值,表示是否找到了参数字符串
  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部
  • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部
    这三种方法都支持第二个参数,表示开始搜索的位置
repeat()

repeat()返回一个新字符串,表示将源字符串重复n次,只针对字符串做操作!

'x'.repeat(3) //xxx

模板字符串

let name ='cindy'
let a = `my name is ${name}`
console.log(a) //my name is cindy

若使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中

字符串模板中还能调用函数

function fn(){
    return "Hello world"
}

`foo ${fn()} bar` //"foo Hello world bar"

大括号内可以放任意表达式、函数、变量

正则的扩展

数值的扩展

函数的扩展

函数参数允许指定默认值
function log(x,y = 'world'){
    console.log(x,y);
}
log('Hello') // "Hello world"
log('Hello','cindy') // "Hello cindy"
log('Hello','') // "Hello"

函数的length属性

返回没有置顶默认值的参数个数

(function (a){}).length //1
(function (a=1){}),length //0

箭头函数

可以使用一个圆括号代表参数部分

var f = () =>5
//相当于
var f = function (){
    return 5
}

var sum = (num1,num2)=>num1+num2;
//等同于
var sum = function (num1,num2){
    return num1+num2;
}

箭头函数的使用注意点
  • 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象!
  • 不可以当作构造函数,也就是说,不能使用new,否则会抛出一个错误。
  • 使用rest代替arguments对象
  • 箭头函数不可以作为generator函数

this对象的指向是可变的,但是在箭头函数中,他是固定的

箭头函数根本没有自己的this,导致内部this就是外层代码块的this,正是因为没有this, 所以不能用作构造函数。

// ES6
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

// 等同于 ES5
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log('id:', _this.id);
  }, 100);
}
//转换后的 ES5 版本清楚地说明了,箭头函数里面根本没有自己的this,而是引用外层的this。

请问下面的代码之中有几个this?

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
双冒号运算符

由于箭头函数并不适用于所有场合,因此“函数绑定”运算符,用来取代call、bind、apply调用

函数绑定运算符是并排的两个冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。

foo::bar;
// 等同于
bar.bind(foo);

foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);

const hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
  return obj::hasOwnProperty(key);
}

代替函数的apply方法

由于扩展运算符可以展开数组,因此不再需要apply方法,下面是利用扩展运算符求一个数组最大元素的例子

//es5
Math.max.apply(null,[1,23,4,5,3])

//es6
Math.max(...[1,23,4,5,3])

//等同于
Math.max(1,23,4,5,3)


扩展运算符的应用
  • 复制数组
    es5中复制数组的时候只是复制了底层数据结构的指针,更改a2会影响a1,但使用了扩展运算符会避免这个问题
const a1=[1,2]
const a2=[...a1]
a2[0]=0
a2 //[0,2]
a1 //[1,2]

  • 合并数组
[...arr1,...arr2,...arr3]

Array.from()

Array.from 方法用于将两类对象转为真正的数组。

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};

let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

Array.of()

Array.of()用于将一组数值,转换为数组

对象的扩展

属性的便利
  • for…in 循环遍历对象自身的和继承的可枚举属性
  • Object.keys(obj) 返回一个数组,包括对象自身(不含继承)所有枚举属性的键名
  • Object.getOwnPropertyNames(obj) 返回一个数组,包含对象自身的所有属性的键名
  • Object.getOwnPropertySymbols(obj)返回一个数组,包含对象自身的所有 Symbol 属性的键名。
  • Reflect.ownKeys(obj) 返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
super 关键字

指向当前对象的原型对象

对象新增的方法

Object.is()

用来比较两个值是否严格相等。

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

+0 === -0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
Object.assign()

Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。

const target = { a: 1, b: 1 };

const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

  • Object.assign 实行的是浅拷贝

Set

类似于数组,但是成员的值都是唯一的,因此可以用来去重

[...new Set(array)]
相关标签: es6