From 5258e43dd01e62498cbc6c58be7393c00b6c15f5 Mon Sep 17 00:00:00 2001 From: ruanyf Date: Wed, 19 Oct 2016 14:00:22 +0800 Subject: [PATCH] =?UTF-8?q?docs(function):=20=E4=BD=BF=E7=94=A8=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E9=BB=98=E8=AE=A4=E5=80=BC=EF=BC=8C=E4=B8=8D=E8=83=BD?= =?UTF-8?q?=E5=9C=A8=E5=87=BD=E6=95=B0=E5=86=85=E9=83=A8=E6=98=BE=E5=BC=8F?= =?UTF-8?q?=E5=BC=80=E5=90=AF=E4=B8=A5=E6=A0=BC=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/function.md | 78 ++++++++++++++++++++++++++++++++++++++++++++++- docs/reference.md | 1 + 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/docs/function.md b/docs/function.md index 7df8a5c..b7f82ec 100644 --- a/docs/function.md +++ b/docs/function.md @@ -694,6 +694,82 @@ var obj = {a: 1, b: 2}; let arr = [...obj]; // TypeError: Cannot spread non-iterable object ``` +## 严格模式 + +从ES5开始,函数内部可以设定为严格模式。 + +```javascript +function doSomething(a, b) { + 'use strict'; + // code +} +``` + +《ECMAScript 2016标准》做了一点修改,规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。 + +```javascript +// 报错 +function doSomething(a, b = a) { + 'use strict'; + // code +} + +// 报错 +const doSomething = function ({a, b}) { + 'use strict'; + // code +}; + +// 报错 +const doSomething = (...a) => { + 'use strict'; + // code +}; + +const obj = { + // 报错 + doSomething({a, b}) { + 'use strict'; + // code + } +}; +``` + +这样规定的原因是,函数内部的严格模式,同时适用于函数体代码和函数参数代码。但是,函数执行的时候,先执行函数参数代码,然后再执行函数体代码。这样就有一个不合理的地方,只有从函数体代码之中,才能知道参数代码是否应该以严格模式执行,但是参数代码却应该先于函数体代码执行。 + +```javascript +// 报错 +function doSomething(value = 070) { + 'use strict'; + return value; +} +``` + +上面代码中,参数`value`的默认值是八进制数`070`,但是严格模式下不能用前缀`0`表示八进制,所以应该报错。但是实际上,JavaScript引擎会先成功执行`value = 070`,然后进入函数体内部,发现需要用严格模式执行,这时才会报错。 + +虽然可以先解析函数体代码,再执行参数代码,但是这样无疑就增加了复杂性。因此,标准索性禁止了这种用法,只要参数使用了默认值、解构赋值、或者扩展运算符,就不能显式指定严格模式。 + +两种方法可以规避这种限制。第一种是设定全局性的严格模式,这是合法的。 + +```javascript +'use strict'; + +function doSomething(a, b = a) { + // code +} +``` + +第二种是把函数包在一个无参数的立即执行函数里面。 + +```javascript +const doSomething = (function () { + 'use strict'; + return function(value = 42) { + return value; + }; +}()); +``` + ## name属性 函数的`name`属性,返回该函数的函数名。 @@ -1061,7 +1137,7 @@ var fix = f => (x => f(v => x(x)(v))) 上面两种写法,几乎是一一对应的。由于λ演算对于计算机科学非常重要,这使得我们可以用ES6作为替代工具,探索计算机科学。 -## 函数绑定 +## 绑定 this 箭头函数可以绑定`this`对象,大大减少了显式绑定`this`对象的写法(`call`、`apply`、`bind`)。但是,箭头函数并不适用于所有场合,所以ES7提出了“函数绑定”(function bind)运算符,用来取代`call`、`apply`、`bind`调用。虽然该语法还是ES7的一个[提案](https://github.com/zenparsing/es-function-bind),但是Babel转码器已经支持。 diff --git a/docs/reference.md b/docs/reference.md index e6b922c..b0b0e37 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -83,6 +83,7 @@ - Kyle Simpson, [Arrow This](http://blog.getify.com/arrow-this/): 箭头函数并没有自己的this - Derick Bailey, [Do ES6 Arrow Functions Really Solve “this” In JavaScript?](http://derickbailey.com/2015/09/28/do-es6-arrow-functions-really-solve-this-in-javascript/):使用箭头函数处理this指向,必须非常小心 - Mark McDonnell, [Understanding recursion in functional JavaScript programming](http://www.integralist.co.uk/posts/js-recursion.html): 如何自己实现尾递归优化 +- Nicholas C. Zakas, [The ECMAScript 2016 change you probably don't know](https://www.nczonline.net/blog/2016/10/the-ecmascript-2016-change-you-probably-dont-know/): 使用参数默认值时,不能在函数内部显式开启严格模式 ## 对象