ECMAScript6入门-笔记

此文为ECMAScript 6 入门 - 阮一峰 - 读后笔记
2.let/const
  • let

    • let对应块级作用域,且没有声明提升
    • 暂时性死区

      • 下面示例代码中存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错
      var tmp = 123;
      if (true) {
      tmp = 'abc'; // ReferenceError
      let tmp;
      }
    • 不允许重复声明
  • const
    • 同样只作用于块级作用域
    • 暂时性死区
    • 不允许重复声明
  • ES6为了保持兼容性,var命令和function命令声明的全局变量,依旧是全局对象的属性;而新增的let命令、const命令、class命令声明的全局变量,不属于全局对象的属性。示例如下
var a = 1;
window.a // 1
let b = 1;
window.b // undefined
3.变量的解构赋值
  • 用于数组/对象
    • 数组 [x, y] = [y, x];
    • 对象 {bar, foo } = {foo: "aaa", bar: "bbb" }
    • 字符串可以解构为数组 const [a, b, c, d, e] = 'hello'; /*'h', 'e', 'l', 'l', 'o'*/
  • 解构赋值时,如果等号右边是数值和布尔值,则会先转为对象
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
//Number.prototype.toString和Boolean.prototype.toString均继承自Object
4.字符串的扩展
  • 方法扩展
    • includes():返回布尔值,表示是否找到了参数字符串
    • startsWith():返回布尔值,表示参数字符串是否在源字符串的头部
    • endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部
  • 模板字符串
    • 模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量
    `Hello \${name}, how are you \${time}?`
5.正则的扩展
6.数值的扩展
  • 二进制(0b)和八进制(0o)
  • Math中的很多数学方法
7.数组的扩展
  • Array.from() 将类数组对象转换为数组
// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
  • Array.of 将一组值,转换为数组
  • …更多的数组方法
8.函数的扩展
  • 参数默认值
function Point(x = 0, y = 0) {
  this.x = x;
  this.y = y;
}
var p = new Point();
p // { x: 0, y: 0 }
  • rest参数用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中
// arguments变量的写法
function sortNumbers() {
  return Array.prototype.slice.call(arguments).sort();
}
// rest参数的写法
const sortNumbers = (...numbers) => numbers.sort();
  • 扩展运算符

    • 该运算符主要用于函数调用,好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列

      function push(array, ...items) {
      array.push(...items);
      }
      
      function add(x, y) {
      return x + y;
      }
      var numbers = [4, 38];
      add(...numbers) // 42
    • 任何Iterator接口的对象,都可以用扩展运算符转为真正的数组

      var nodeList = document.querySelectorAll('div');
      var array = [...nodeList];
  • 箭头函数
    • 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
    • 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替
    • 不可以使用yield命令,因此箭头函数不能用作Generator函数
  • 函数绑定(ES7提案)

    • 函数绑定运算符是并排的两个双冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面
      foo::bar;
      // 等同于
      bar.bind(foo);
      
      foo::bar(...arguments);
      // 等同于
      bar.apply(foo, arguments);
  • 尾调用优化
    • 尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用帧,取代外层函数的调用帧就可以了
9.对象的扩展
  • 属性的简洁表示法
var foo = 'bar';
var baz = {foo};
baz // {foo: "bar"}
// 等同于
var baz = {foo: foo};
  • Object.assign(target, source1, source2); 浅拷贝
10.Symbol(不是很懂,存疑)
  • 唯一对象
11.Proxy和Reflect(存疑)
  • Proxy
    • 拦截器
  • Reflect
12.二进制数组(暂时不相关)
13.Set/Map
  • Set
    • 加入到Set内的值不会进行类型转换,因而5'5'是两个不同的值
  • Map

    • JavaScript的对象(Object),本质上是键值对的集合(Hash结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制,故而引入了Map

      • 由于对象只接受字符串作为键名,所以DOM节点对象会被自动转为字符串[object HTMLDivElement],所以在存在多个相同标签的情况下后者会覆盖掉前者导致数据丢失

        var m = {};
        var div = document.createElement('div');
        m[div] = 123;
        var h1 = document.createElement('div');
        m[h1] = 234;
        console.log(m); //{[object HTMLDivElement]: 234}
    • set/get/has/delete/clear方法
    • size属性,存储了成员数量
    • 遍历方法
      • keys():返回键名的遍历器。
      • values():返回键值的遍历器。
      • entries():返回所有成员的遍历器。
      • forEach():遍历Map的所有成员。
      • for…in…/forEach()遍历
  • WeekSet/WeekMap
    • 只接受对象作为元素/键名
    • 弱引用,元素/键名不计入垃圾回收
      • 以此为优势,可以方便的存储一些可能被移除的对象,不担心内存泄漏;例如操作DOM节点
14.Iterator/for…of循环
  • Iterator
15.Generator(此处内容太多,详见原文)
  • Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同
  • Generator函数有多种理解角度。从语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态
  • 执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态
  • 用于异步编程

    • 回调形式

      step1(function (value1) {
          step2(value1, function(value2) {
              step3(value2, function(value3) {
                  step4(value3, function(value4) {
                      // Do something with value4
                  });
              });
          });
      });
    • Promise形式

      Q.fcall(step1)
      .then(step2)
      .then(step3)
      .then(step4)
      .then(function (value4) {
          // Do something with value4
      }, function (error) {
          // Handle any error from step1 through step4
      })
      .done();
    • Generator

      function* longRunningTask() {
          try {
              var value1 = yield step1();
              var value2 = yield step2(value1);
              var value3 = yield step3(value2);
              var value4 = yield step4(value3);
              // Do something with value4
          } catch (e) {
              // Handle any error from step1 through step4
          }
      }

    然后,使用一个函数,按次序自动执行所有步骤

    scheduler(longRunningTask());
    function scheduler(task) {
        setTimeout(function() {
            var taskObj = task.next(task.value);
            // 如果Generator函数未结束,就继续调用
            if (!taskObj.done) {
                task.value = taskObj.value
                scheduler(task);
            }
        }, 0);  //此处延时0ms是为了异步执行,如果没有setTimeout则是同步的
    }
16.Promise对象
  • 三种状态 PendingResolvedRejected
  • 使用方法

    var p = new Promise(function (resolve, reject) {
        console.log('p1');
        setTimeout(function () {
            resolve(1);
        }, 1000);
    });
    
    p.then(
            (val)=>{
                console.log('p2', val);
                return Promise.reject(2);
            },
            (err)=>{}
            )
            .then((val)=>{},
                    (err)=>{
                        console.log('p3 - reject', err);
                        return Promise.resolve(3);
                    }
    
            )
            .then((val)=>{
                        console.log('p4', val);
                    },
                    (err)=>{}
            );
  • Promise.resolve/Promise.reject 分别返回对应状态的Promise实例
17.异步操作和Async函数(ES7)(存疑)
  • Async异步编程解决方案
18.Class
  • constructor方法
    • constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加
  • 不存在变量提升
  • 继承 extends
    • super
      • 作为函数调用时(即super(…args)),super代表父类的构造函数。
      • 作为对象调用时(即super.prop或super.method()),super代表父类。注意,此时super即可以引用父类实例的属性和方法,也可以引用父类的静态方法
    • 静态属性/方法
      • 静态属性/方法的是Class本身的属性/方法,即Class.propname/Class.funcname,而不是定义在实例对象(this)上
18.Decorator(ES7)
19.Module
  • ES6模块加载的实质
    • ES6模块加载的机制,与CommonJS模块完全不同。CommonJS模块输出的是一个值的拷贝,而ES6模块输出的是值的引用
    • export通过接口,输出的是同一个值。不同的脚本加载这个接口,得到的都是同样的实例
20.编程风格
  • 对象尽量静态化,一旦定义,就不得随意添加新的属性。如果添加属性不可避免,要使用Object.assign方法
  • 如果对象的属性名是动态的,可以在创造对象的时候,使用属性表达式定义
// bad
const obj = {
  id: 5,
  name: 'San Francisco',
};
obj[getKey('enabled')] = true;

// good
const obj = {
  id: 5,
  name: 'San Francisco',
  [getKey('enabled')]: true,
};
  • 对象的属性和方法,尽量采用简洁表达法,这样易于描述和书写
// good
var ref = 'some value';
// bad
const atom = {
  ref: ref,
  value: 1,
  addValue: function (value) {
    return atom.value + value;
  },
};
// good
const atom = {
  ref,
  value: 1,
  addValue(value) {
    return atom.value + value;
  },
};
  • 那些需要使用函数表达式的场合,尽量用箭头函数代替。因为这样更简洁,而且绑定了this
  • 注意区分Object和Map,只有模拟现实世界的实体对象时,才使用Object。如果只是需要key: value的数据结构,使用Map结构。因为Map有内建的遍历机制,且键值可以不限于字符串
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值