箭头函数

箭头函数里的this会引用 定义 箭头函数时,外部作用域 的 this 。箭头函数只是 引用 外部作用域的 this ,本身不存在 this。同时因为没有 this ,所以 无法用new生成实例,例:

var name = 'window';
function test(){
//实际等同于这样
//var _this = this;
this.name = 1;
this.method = ()=>{
//console.log(_this.name);
console.log(this.name);
}
}
var b = new test();
setTimeout(b.method, 500);  //1

这个例子中,箭头函数的 this 在定义 method 方法时,引用了test的上下文,而不是执行时引用 this ,所以 setTimeout 方法执行的 method 方法时,this 还是指向了 test 。

function test(){
this.method = ()=>{
function foo(){
console.log(this); //Window
console.log(this instanceof Window); //true
}
foo();
}
}
var b = new test();
setTimeout(b.method, 500);   //1

这个例子中,这个例子中 this 之所以没有引用箭头函数外层,是因为 foo 函数里的 this 作用域此时属于Window,也就不用往 foo 函数外层查找this了,所以 this 指向了 Window。

参数默认值

ES6之前,参数不能给定默认值,只能通过下面的形式给参数设定默认值。

function a(x){
x? x: x = 1;
//或者
if(typeof x === 'undefined'){
x = 1;
}
}

ES6只要下面的形式就能给参数设定默认值

function a(x = 1){
console.log(x); //1
}

如果给参数赋予一个默认的函数,就会出现特殊情况。例1:

var x = 0;
function a(x, y = ()=> {x = 1; console.log(x); /* 1 */ }){
var x = 10;
y();
console.log(x); //10
}
a();
console.log(x); //0

参数y里的代码执行之后,函数 y 里的 x 确实已经被赋值了 1,但是函数体内的 x 值还是10,同时全局变量 x 也还是0。

假如把例1里的函数 y 从默认值里放到函数 a 内部,则会变成这样。

var x = 0;
function a(x, y){
if(typeof y === 'undefined'){
y = ()=> {
x = 1;
}
}
var x = 10;
y();
console.log(x); //1
}
a();
console.log(x); //0

结果是 x = 1 把前面的 x = 10 给覆盖了,当然全局变量依然没有变化。

这两个例子看似一样,但实际上,ES6的机制是:参数默认值是一个函数时,会生成一个参数级作用域。导致这两个例子本质上有所差别,同时函数体内部是函数级作用域,函数外部是外部作用域。三个作用域互相独立,又由作用域链引用。从内往外的顺序是:

函数级作用域 => 参数级作用域 => 外部作用域

函数a => 参数 x, y 所在的括号部分 => 全局变量        (以例1为例)

注意下面这种情况:

function a(x, y = ()=> {var b = 10; console.log(b)}){
y(); //10
console.log(b); //报错 b is not defined
}
a();

参数级作用域只是参数声明的括号部分,而参数 y 内部的作用域对参数级作用域不可见。

也就是变量 b 被函数 y 的作用域隔离开了,不属于参数级作用域,也就无法给函数 a 所捕获。

而例1 中在声明函数的时候,会同时(也许是执行的时候,暂不清楚)声明变量 x 与 函数 y。由于已经声明了变量 x,同时 x 和 y 同属块级作用域。以及作用域链的存在,外部作用域无法查找内部作用域里的变量,只能往外查找变量。按照 函数级作用域 => 块级作用域 => 外部作用域 的顺序,参数部分的块级作用域无法调用函数内部的变量。

所以例子中的 x 实际上被定义了3次,每一个作用域各1次,也就导致了每个作用域中的 x 的值互相独立赋值。

所以实际上例1编译成ES5的代码是下面这样的:

var x = 0;
function a(x, y){
y = function() {
x = 1; //参数里已经声明了变量x,所以不是全局里的x
console.log(x); //1
}
return function(){
var x = 10;
y();
console.log(x); //10
}()
}
a();
console.log(x); //0

ES6里实现则是:

var x = 0;
function a(x, y){
y = function() {
x = 1; //参数里已经声明了变量x,所以不是全局里的x
console.log(x); //1
}
{
let x = 10; //用let声明一个块级变量
y();
console.log(x); //10
}
}
a();
console.log(x); //0

假设把例1改成下面这样:

var x = 0;
function a(x, y = ()=> {x = 1; console.log(x); /* 1 */ }){
x = 10; //去掉var
y();
console.log(x); //1
}
a();
console.log(x); //0

在去掉了函数级作用域里的 var 关键字后,变量 x 和 参数 x 都处于同一作用域(chrome控制台显示为local,也就是函数级作用域,可能是为了兼容ES5)。此时 y 里的 x = 1 就覆盖了 x = 10。

Generator 函数与异步

Generator函数的yield没有本身不会有返回值,除非在next方法里带上参数,这个参数会变成上一个yield语句的返回值。

例:

function* f() {
for(var i = 0; true; i++) {
var reset = yield i;
console.log(reset, i);
if(reset) { i = -1; }
}
} var g = f(); g.next()
//undefined, 0
// { value: 0, done: false } g.next()
//undefined, 1
// { value: 1, done: false } g.next(true)
//true, 0
// { value: 0, done: false }

如果内部有return一个值, 那么无论后面是否还有yield,直接返回对象。对象中的value属性就是那个值,done值为true,也即完成。

ES6 笔记的更多相关文章

  1. ES6笔记(5)-- Generator生成器函数

    系列文章 -- ES6笔记系列 接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术. 在异步编程中,还 ...

  2. ES6笔记系列

    ES6,即ECMAScript 6.0,ES6的第一个版本是在2015年发布的,所以又称作ECMAScript 2015 如今距ES6发布已经一年多的时间,这时候才去学,作为一个JSer,羞愧羞愧,还 ...

  3. ES6笔记(1) -- 环境配置支持

    系列文章 -- ES6笔记系列 虽然ES6已经发布一年多了,但在各大浏览器之中的支持度还不是很理想,在这查看ES6新特性支持度 Chrome的最新版本浏览器大部分已经支持,在Node.js环境上支持度 ...

  4. ES6笔记(2)-- let的块级作用域

    系列文章 -- ES6笔记系列 一.函数级作用域 我们都知道,在ES6以前,JS只有函数级作用域,没有块级作用域这个概念 没有块级作用域,有利有弊,利于方便自由,弊于作用域内的变量容易被共享,例如这个 ...

  5. ES6笔记(3)-- 解构赋值

    系列文章 -- ES6笔记系列 解构赋值,即对某种结构进行解析,然后将解析出来的值赋值给相关的变量,常见的有数组.对象.字符串的解构赋值等 一.数组的解构赋值 function ids() { ret ...

  6. ES6笔记(4)-- Symbol类型

    系列文章 -- ES6笔记系列 Symbol是什么?中文意思是标志.记号,顾名思义,它可以用了做记号. 是的,它是一种标记的方法,被ES6引入作为一种新的数据类型,表示独一无二的值. 由此,JS的数据 ...

  7. ES6笔记(6)-- Set、Map结构和Iterator迭代器

    系列文章 -- ES6笔记系列 搞ES6的人也是够无聊,把JS弄得越来越像Java.C++,连Iterator迭代器.Set集合.Map结构都出来了,不知道说什么好... 一.简单使用 1. iter ...

  8. ES6笔记(7)-- Promise异步编程

    系列文章 -- ES6笔记系列 很久很久以前,在做Node.js聊天室,使用MongoDB数据服务的时候就遇到了多重回调嵌套导致代码混乱的问题. JS异步编程有利有弊,Promise的出现,改善了这一 ...

  9. ES6 笔记汇总

    ES6 笔记汇总 二.ES6基础-let和const命令 三.变量的解构赋值 四.字符串的拓展 五.正则表达式的拓展 ...将会持续更新,敬请期待

  10. ES6笔记2

    ES6笔记2 Promise Promise 是 ES6 引入的异步编程的新解决方案,语法上是一个构造函数 一共有3种状态,pending(进行中).fulfilled(已成功)和rejected(已 ...

随机推荐

  1. javascript数据结构和算法

    一.栈 javascript实现栈的数据结构(借助javascript数组原生的方法即可) //使用javascript来实现栈的数据结构 var Stack={ //不需要外界传参进行初始化,完全可 ...

  2. delphi之事件

    delphi的事件如上图所示: 图中oncloseup代表的是日期选择下拉框关闭时触发的事件. //事件定义 procedure Ondatechange(Sender: TObject); //事件 ...

  3. lintcode bugfree and good codestyle note

    2016.12.4, 366 http://www.lintcode.com/en/problem/fibonacci/ 一刷使用递归算法,超时.二刷使用九章算术的算法,就是滚动指针的思路,以前写py ...

  4. MWeb 1.6 发布!Dark Mode、全文搜寻、发布到Wordpress、Evernote 等支持更新、编辑/预览视图模式等

    Dark Mode 使用 View - Dark Mode 或快捷键 CMD + Option + L 开启或关闭 Dark Mode.可以在设置中设置 Dark Mode 状态下编辑器所使用的样式, ...

  5. JMX

    一.为什么使用JMX,解决那些问题 举一个应用实例:在一个系统中常常会有一些配置信息,比如服务的IP地址,端口号什么的,那么如何来写这些代码呢? 写死在程序里,到要改变时就去改程序,然后再编译发布: ...

  6. SpringMVC整合Hibernate实现增删改查之按条件查询

    首先我贴出我项目的结构,只完成了条件查询的相关代码,增删改没有写. 1.新建一个动态Web工程,导入相应jar包,编写web.xml配置文件 <context-param> <par ...

  7. CAS学习笔记(一)

    近期做单点登录,看了一些CAS资料,做下总结 一.cas简介 全名:Central Authentication Service 特点: 1.开源的.多协议的 SSO 解决方案: Protocols  ...

  8. jQuery ajax的traditional参数的作用///////////////////////////////////zzzzzzzzzzz

    jQuery ajax的traditional参数的作用 i33 发布时间: 2013/04/03 10:05 阅读: 9859 收藏: 9 点赞: 1 评论: 0 一般的,可能有些人在一个参数有多个 ...

  9. (转)学习使用Jmeter做压力测试(一)--压力测试基本概念

    一.性能测试的概念 性能测试是通过自动化的测试工具模拟多种正常峰值及异常负载条件来对系统的各项性能指标进行测试.负载测试和压力测试都属于性能测试,两者可以结合进行. 通过负载测试,确定在各种工作负载下 ...

  10. 浅谈js回调函数

    回调函数原理: 我现在出发,到了通知你”这是一个异步的流程,“我出发”这个过程中(函数执行),“你”可以去做任何事,“到了”(函数执行完毕)“通知你”(回调)进行之后的流程 例子 1.基本方法 ? 1 ...