function*

function* 这种声明方式(function关键字后跟一个星号)会定义一个生成器函数 (generator function),它返回一个  Generator  对象。

你也可以定义 生成器函数  使用构造函数  GeneratorFunction 和一个  function* expression 。

语法

function* name([param[, param[, ... param]]]) { statements }
name
函数名
param
要传递给函数的一个参数的名称,一个函数最多可以有255个参数。
statements
普通JS语句。

描述

生成器函数在执行时能中途退出,后面又能重新进入继续执行。而且在函数内定义的变量的状态都会保留,不受中途退出的影响。

调用一个生成器函数并不会马上执行它里面的语句,而是返回一个这个生成器的迭代器(iterator)对象。当这个迭代器的 next() 方法被首次(后续)调用时,其内的语句会执行到第一个(后续)出现yield表达式的位置为止,该表达式定义了迭代器要返回的值,或者被 yield*委派至另一个生成器函数。next()方法返回一个对象,这个对象包含两个属性:value 和 done,value 属性表示本次 yield 表达式的返回值,done 属性为布尔类型,表示生成器是否已经产出了它最后的值,即生成器函数是否已经返回。

调用 next() 方法时,如果传入了参数,那么这个参数会取代生成器函数中对应执行位置的 yield 表达式(整个表达式被这个值替换)

当在生成器函数中显式 return 时,会导致生成器立即变为完成状态,即调用 next() 方法返回的对象的 done 为 true。如果 return了一个值,那么这个值会作为下次调用 next() 方法返回的 value 值。

示例

简单示例

  • function* idMaker(){
  • var index = 0;
  • while(index<3)
  • yield index++;
  • }
  •  
  • var gen = idMaker();
  •  
  • console.log(gen.next().value); // 0
  • console.log(gen.next().value); // 1
  • console.log(gen.next().value); // 2
  • console.log(gen.next().value); // undefined
  •  
Arrow function

基本用法

ES6允许使用“箭头”(=>)定义函数。

var f = v => v;
 

上面的箭头函数等同于:

var f = function(v) {
return v;
};
 

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

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

如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。

var sum = (num1, num2) => { return num1 + num2; }
 

由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号。

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

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

const full = ({ first, last }) => first + ' ' + last;

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

使用注意点

箭头函数有几个使用注意点。

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

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

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

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

this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。

除了this,以下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:argumentssupernew.target

function foo() {
setTimeout(() => {
console.log('args:', arguments);
}, 100);
} foo(2, 4, 6, 8)
// args: [2, 4, 6, 8]
 

上面代码中,箭头函数内部的变量arguments,其实是函数fooarguments变量。

另外,由于箭头函数没有自己的this,所以当然也就不能用call()apply()bind()这些方法去改变this的指向。

(function() {
return [
(() => this.x).bind({ x: 'inner' })()
];
}).call({ x: 'outer' });
// ['outer']
 

上面代码中,箭头函数没有自己的this,所以bind方法无效,内部的this指向外部的this

长期以来,JavaScript语言的this对象一直是一个令人头痛的问题,在对象方法中使用this,必须非常小心。箭头函数”绑定”this,很大程度上解决了这个困扰。

函数绑定

箭头函数可以绑定this对象,大大减少了显式绑定this对象的写法(callapplybind)。但是,箭头函数并不适用于所有场合,所以ES7提出了“函数绑定”(function bind)运算符,用来取代callapplybind调用。虽然该语法还是ES7的一个提案,但是Babel转码器已经支持。

函数绑定运算符是并排的两个双冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即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);
}
 

如果双冒号左边为空,右边是一个对象的方法,则等于将该方法绑定在该对象上面。

var method = obj::obj.foo;
// 等同于
var method = ::obj.foo; let log = ::console.log;
// 等同于
var log = console.log.bind(console);
 

由于双冒号运算符返回的还是原对象,因此可以采用链式写法。

尾调用优化

什么是尾调用?

尾调用(Tail Call)是函数式编程的一个重要概念,本身非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。

function f(x){
return g(x);
}
 

上面代码中,函数f的最后一步是调用函数g,这就叫尾调用。

“尾调用优化”(Tail call optimization),即只保留内层函数的调用帧。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用帧只有一项,这将大大节省内存。这就是“尾调用优化”的意义。

严格模式

ES6的尾调用优化只在严格模式下开启,正常模式是无效的。

这是因为在正常模式下,函数内部有两个变量,可以跟踪函数的调用栈。

  • func.arguments:返回调用时函数的参数。
  • func.caller:返回调用当前函数的那个函数。

尾调用优化发生时,函数的调用栈会改写,因此上面两个变量就会失真。严格模式禁用这两个变量,所以尾调用模式仅在严格模式下生效。

function restricted() {
"use strict";
restricted.caller; // 报错
restricted.arguments; // 报错
}
restricted();
 

箭头函数与常规函数对比

一个箭头函数与一个普通的函数在两个方面不一样:

  • 下列变量的构造是词法的: arguments , super , this , new.target
  • 不能被用作构造函数:没有内部方法 [[Construct]] (该方法允许普通的函数通过 new 调用),也没有 prototype 属性。因此, new (() => {}) 会抛出错误。

除了那些意外,箭头函数和普通的函数没有明显的区别。例如, typeof 和 instanceof 产生同样的结果:

> typeof () => {}
//'function'
> () => {} instanceof Function
//true > typeof function () {}
//'function'
> function () {} instanceof Function
//true
 

函数表达式和对象字面量是例外,这种情形下必须放在括号里面,因为它们看起来像是函数声明和代码块。

js之function的更多相关文章

  1. JS 关于(function( window, undefined ) {})(window)写法的理解

    JS 关于(function( window, undefined ) {})(window)写法的理解 [网络整理] (function( window, undefined ) {})(windo ...

  2. js小记 function 的 length 属性

    原文:js小记 function 的 length 属性 [1,2,3]., ,这个略懂js的都知道. 但是  eval.length,RegExp.length,"".toStr ...

  3. js中function的与众不同

    js中function的与众不同在于可以被调用

  4. JS里面function和Function的区别

    js里Function 与 function的不一样的,不仅仅是大小写的问题. 简单点说:大写的Function是一个类 ,而小写的function是一个对象. Function是一个构造器,func ...

  5. js arrow function return object

    js arrow function return object bug filterData: { type: Object, default: () => {}, required: true ...

  6. how to remove duplicates of an array by using js reduce function

    how to remove duplicates of an array by using js reduce function ??? arr = ["a", ["b& ...

  7. js currying function All In One

    js currying function All In One js 实现 (5).add(3).minus(2) 功能 例: 5 + 3 - 2,结果为 6 https://stackoverflo ...

  8. Js函数function基础理解

    正文:我们知道,在js中,函数实际上是一个对象,每个函数都是Function类型的实例,并且都与其他引用类型一样具有属性和方法.因此,函数名实际上是指向函数对象的指针,不与某个函数绑定.在常见的两种定 ...

  9. js中function函数

    function:是具备某个功能的方法,方法本身没有意义,只有执行方法才有价值. function: 1 创建一个函数: 2 执行这个方法: 例: 创建 function 方法名(){ 存放某个功能的 ...

  10. js中function参数默认值

    --在dreamweaver做网站时,函数定义是在一个*.js文件中,其中定义了一个func,有四个参数,function func(string1,url,flag,icon),然后在另一个asp中 ...

随机推荐

  1. Java拦截器+注解搭配使用

    拦截器加注解可以实现登录权限验证等操作,我的应用场景也是为了验证这个,下面是简单的实现步骤   一.什么是拦截器? 拦截器是对action的一种拦截,可以在请求前后进行一些处理 可拦截controll ...

  2. java并发:CopyOnWriteArrayList简单理解

    Java集合的快速失败机制 “fail-fast” "fail-fast"是java集合的一种错误检测机制,当多个线程对集合进行结构上的改变的操作时,有可能会产生 fail-fas ...

  3. Python hash() 函数

    Python hash() 函数  Python 内置函数 描述 hash() 用于获取取一个对象(字符串或者数值等)的哈希值. 语法 hash 语法: hash(object) 参数说明: obje ...

  4. layer数据表格换行

    在使用layer数据表格的时候,默认是不可以换行的.这样显示 改动后 数据格式为   aa<br>bb就会显示为换行 比如我们的字符串是    a<br>b 这样的字符串浏览器 ...

  5. Python+Selenium学习--打印当前页面的title及url

    场景 测试中,访问1个页面然后判断其title是否符合预期是很常见的1个用例,所谓用例不够,title来凑就是这个道理.更具体一点,假设1个页面的title应该是'hello world', 那么可以 ...

  6. Lua入门教程

    什么是Lua Lua 是一个小巧的脚本语言.是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组,由Rober ...

  7. f5创建monitor

  8. f5版本升级

    1)上传系统IOS及Hotfix 点击import按钮,选择要上传的文件.上传成功的话就会显示上传成功的10.2.4的iso文件 2)通过CLI命令行方式上传补丁 通过SSH工具将ISO以及Hotfi ...

  9. windows 2012安装不了KB2919355

    直接安装KB2919355会报错 “此更新不适用于你的计算机” 此时应先安装 KB2919442 https://www.microsoft.com/zh-cn/download/confirmati ...

  10. crm作业知识点集合[三]

    知识点1 我们要实现一个这样的功能,在学生表中,可以查看每个学生的报名的班级的所有的成绩,就是下图的效果 1.首先我们需要在学生表中自定义一列,这一列的内容就是一个a标签,指向另外一个页面,而我们在另 ...