阮一峰ES6读书笔记

let和const命令

  • let命令
    • let命令只在所在的代码块内有效
    • for循环有一个特别之处,设置循环变量那部分是一个父作用于,而循环体内部是一个单独的子作用域
    • 不存在变量提升
    • 暂时性死区
      • 只要块级作用于内存在let和const命令,这个区域对这些命令声明的变量,从一开始就形成了封闭作用于
      • 本质:只要已进入当前作用域,索要使用的变量就已经存在了,但是不可获取,只有等到声明变量的哪一行代码出现,才可以获取和使用该变量
    • 不允许重复声明
  • 块级作用域
    • 防止内层变量覆盖外层变量;防止用来计数的循环变量泄露为全局变量。
    • 使得立即执行函数表达式不再必要了
    • 块级作用域之中可以声明函数。块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用
    • 浏览器环境下比较特殊
      • 允许在块级作用域内声明函数
      • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部
      • 同时,函数声明还会提升到所在的块级作用域的头部
  • const命令
    • 声明一个只读的常量,一旦声明,常量的值就不能改变

    • 只在声明所在的块级作用域内有效

    • 不存在变量提升、存在暂时性死区

    • 不允许重复声明

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

      • 对于普通类型的数据,值就保存在变量指向的那个内存地址,因此等同于常量
      • 对于复合类型的数据,变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针的固定的 ,至于它定向的数据结构是不是可变的,就完全不可控了。
    • 将一个复合类型数据声明为常量

       const foo = {};
      		foo.prop = 123;//为foo添加一个属性,可以成功
      		foo = {};//将foo指向另一个对象,就会报错
      
      • 不可变的只是地址,对象本身是可变的。
      • 如果真的想将对象冻结,应该使用Object.freeze方法
         const foo = Object.freeze({});
        		foo.prop = 123;//常规模式下,下面一行不起作用;use strict时,报错
        
      • 除了对象本身冻结,属性也想冻结可以
        var constantize = (obj) => {
           Object.freeze(obj);
           Object.keys(obj). forEach( (key, i) => {
           	if ( typeof obj[key] === 'object' ) {
           		constantize( obj[key] );
           	}
           });
        };
        
    • ES6声明变量的六种方法

      • var、function、let、const、import、class
  • 顶层对象的属性
    • 浏览器环境中指的是window对象;Node中指的是global对象;ES5中与全局变量等价
    • ES6:var和function声明的全局变量,依旧是顶层对象的属性;另一方面,let、const、class声明的全局变量,不属于顶层对象的属性,从ES6开始,全局变量将逐渐与顶层对象的属性脱钩。
  • global对象
    • ES5的顶层对象,本身也是一个问题,因为它在各种实现里面是不统一的。
      • 浏览器里面,顶层对象是window,但Node和Web Worker没有window
        (Web Worker是运行在后台的JS,不会影响页面的性能)
      • 浏览器和Web Worker里面,self也指向顶层对象,但Node没有self
      • Node里面,顶层对象是global,但其他环境都不支持
    • 同一段代码为了能够在各种环境,都能取到顶层对象,现在一般是使用this变量,但是有局限性
      • 全局环境中,this会返回顶层对象。但是,Node模块和ES6模块中,this返回的是当前模块。
      • 函数里面的this,如果函数不是作为兑现改的方式运行,而是单纯作为函数运行,this会指向顶层对象。
    • TO CONTINUE…

变量的解构赋值

  • 数组的解构赋值
    • 基本用法
      • 按照一定模式,从数组和对象中提取值,对变量进行赋值
      • 本质上:这种写法属于"模式匹配",只要等号两边的模式相同,左边的变量就会被赋予对应的值。
      • 如果解构不成功,变量的值就等于undefined
      • 不完全解构:等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。
      • 如果等号右边不是数组(或者严格的说,不是可遍历的结构),将会报错。
      • Set结构,也可使用数组的解构赋值
      • 事实上,只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值
    • 默认值
      • 解构赋值允许指定默认值
      • ES6内部使用严格相等运算符,判断一个位置是否有值。所有,只有当一个数组成员严格等于undefined,默认值才会生效
      • 如果默认值时一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值
      • 默认值可以引用结构赋值的其他变量,但该变量必须已经声明
  • 对象的解构赋值
    • 基本用法
      • 对象的解构与数组有一个重要的不同:数组的元素时按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值
      • 如果变量名与属性名不一致,必须写成下面这样
        • let {first: f, last: l } = {first: ‘aaa’, last: ‘bbb’ }
        •   f//'aaa' l//'bbb'
          
      • 实质上:对象的解构赋值的内部机制,是先找同名属性,然后再赋给对应的变量。真正被赋值的是后者(同名属性对应的变量),而不是前者
      • 如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错
      • 如果要将一个已经声明的变量用于解构赋值,必须非常小心,因为JS引擎会将{}理解成一个代码块,从而发生语法错误,可以写成({})
      • 解构赋值允许等号左边的模式之中,不放置任何变量名。
        • ({} = [true, false])
        • ({} = ‘abc’)
        • ({} = [])
        • 上面的表达式虽然毫无意义,但是语法是合法的,可以执行
      • 对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量
        • let { log, sin, cos} = Math
      • 数组本质是特殊的而对象,因此可以对数组进行对象属性的解构
    • 默认值
      • 默认值生效的条件是,对象的属性值严格等于undefined
  • 字符串的解构赋值
    • 字符串也可以解构赋值,字符串被转换成了一个而类似数组的对象
    • 类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值
  • 数组和布尔值的解构赋值
    • 解构赋值时,如果等号右边是数值和布尔值,则会先转为对象
    • 解构赋值的规则是:只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错
  • 函数参数的解构赋值
    • 函数的参数也可以使用解构赋值
  • 圆括号问题
    • 不能使用圆括号的情况
      • 变量声明语句,模式不能使用圆括号
      • 函数参数
      • 赋值语句的模式
    • 可以使用圆括号的情况
      • 赋值语句的非模式部分,可以使用圆括号
  • 用途
    • 交换变量的值
       let x = 1;
      		let y = 2;
      		[x,y] = [y,x]
      		```
      
    • 从函数返回多个值
      • 函数只能返回一个值,如果要返回多个值,只能讲它们放在数组或对象里返回
      		var example = () => { return [1, 2, 3] }
      		let [a, b, c] = example()
      		```
      
    • 函数参数的定义
      • 解构函数可以方便地将一组参数与变量名对应起来
      		var f = ([x, y, z]) => {}
      		f([1 ,2 ,3])
      		f({z: 1, x: 3, y: 2})
      		```
      
    • 提取JSON数据
    		 let jsonData = {
    			id: 42,
    			status: "OK",
    			data: [867,5309]
    		}
    		let { id, status, data: number } = jsonData
    		console.log(id, status, number)
    		```
    + 函数参数的默认值
    	```javascript
    		jQuery.ajax = function(url, {
    			async = true,
    			beforeSend = function() {},
    			cache = true,
    			complete = function() {},
    			crossDomain = false,
    			global = true,
    				// ...more config
    			} = {}) {
    				// ...do stuff
    			}
    			```
    + 遍历Map结构
    	* 任何部署了Iterator接口的对象,都可以用for...of循环遍历。
    	* Map解构原生支持Iterator接口,配合变量的解构赋值,获取键名和键值就非常方便
    	```javascript
    		const map = Map();
    		map.set('first', 'hello');
    		map.set('second', 'world');
    		for(let [key, value] of map) {
    			console.log(key + " is " + value)
    		}
    		* 如果只想获取键名,获取只想获取键值
    		for(let [key] of map) {
    			//获取键名
    		}
    		for(let [,value] of map){
    			//获取键值
    		}
    		```
    + 数模块的指定方法
    	* 加载模块时,往往需要指定输入哪些方法。解构赋值是的输入语句非常清晰
    	* const { SourceMapConsumer, SourceNode } = require("source-map")
    
    
    

函数的拓展

  • 函数参数的默认值
    • ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法
      • y = y||‘hello’
      • if(typeof y === ‘undefined’){ y = ‘hello’}
    • ES6允许为函数的参数设置默认值,即直接写在参数定义的后面
      • 参数变量是默认声明的,所以不能用let或const再次声明,否则会报错
      • 使用参数默认值时,函数不能有同名参数,否则报错
      • 参数默认值不是传值的,而是每次都重新计算默认值表达式的值;参数默认值时惰性求值的
    • 与解构赋值默认值结合使用
    • 参数默认值的位置
    • 函数的length属性
    • 作用域
    • 应用
  • rest参数
    • ...变量名
  • 严格模式
  • name属性
  • 箭头函数
  • 双冒号运算符
  • 尾调用优化
  • 函数参数的尾逗号

Promise对象

  • Promise是异步编程的一种解决方法,ES6将其写进语言标准,原生提供了Promise对象
  • 两个特点
    • 对象的状态不受外界影响
      • Promise对象代表着一个异步操作,有三种状态
        • pending、fulfilled、rejected
    • 一旦状态改变,就不会再变,任何时候都可以得到这个结果
      • Promise对象的状态改变只有两种可能
        • 从pending->fulfilled
        • 从pending->rejected
    • resolved(已定型),统一只指fulfilled状态,不包含rejected状态
  • 缺点
    • 无法取消Promise,一旦新建它就会立即执行,无法中途取消
    • 如果不设置callback,Promise内部抛出的错误,不会反映到外部
    • 出于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
    • 如果某些事件不断地反复发生,一般来说,使用Stream模式是比部署Promise更好的选择
  • 基本用法
  • Promise.prototype.then()
  • Promise.prototype.catch()
    +.then(null,rejection)的别名,用于指定发生错误时的回调函数
  • Promise.prototype.finally()
    • 用于指定不管Promise对象最后状态如何,都会执行的操作。该方法是ES2018引入标准的
  • Promise.all()
    • 用于将多个Promise实例,包装成一个新的Promise实例
  • Promise.race()
    • 同样式将多个Promise实例,包装成一个新的Promise实例
  • Promise.resolve()
    • 将现有对象转为Promise对象
  • Promise.reject()
    • Promise.reject(reason)方法会返回一个新的Promise实例,该实例的状态为rejected
  • 应用
    • 加载图片
    • Generator函数与Promise的结合
  • Promise.try()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值