函数
-
do
可以形成闭包,和lua
一样。(事实上,do
类似lisp中的let
。) - 隐式返回最后一个表达式的值
- 函数调用省略括号
- 用
arguments
数组访问传递给函数的所有对象(低可读性)
@name
为this.name
的简写,this
表示上下文环境。相应的,有new
关键字,apply
和call
方法。
- 函数调用前若有
new
关键字,会把函数作为构造函数创建一个新对象,上下位即为该新对象。 - 使用
call
或者apply
调用函数时,给定的第一个参数为上下文。 - 函数作为对象的属性
obj.func
来调用时,该对象为上下文。 - 若不满足以上条件,则上下文为全局。
由于上下文在调用时绑定,因此可能会出现预料之外的情况。将->
改为=>
,可以确保this
的意义与函数定义所在位置的this
一样。
属性参数可以缩短代码,如
setName = (name) -> @name = name
可以简写为
setName = (@name) ->
使用表达式作默认参数,则表达式将在函数被调用的上下文中执行。
函数调用可以写成do f
。例如do (x) -> ...
是((x) -> ...)(x)
的简写,这个例子是node.js循环中捕获变量的常用写法。
=>箭头函数表达式:
不绑定this
在箭头函数出现之前,每个新定义的函数都有它自己的 this
值(在构造函数的情况下是一个新对象,在严格模式的函数调用中为 undefined,如果该函数被作为“对象方法”调用则为基础对象等)。This
被证明是令人厌烦的面向对象风格的编程。
function Person() { // Person() 构造函数定义 `this`作为它自己的实例. this.age = 0; setInterval(function growUp() { // 在非严格模式, growUp()函数定义 `this`作为全局对象, // 与在 Person()构造函数中定义的 `this`并不相同. this.age++; }, 1000); } var p = new Person();
在ECMAScript 3/5中,通过将this
值分配给封闭的变量,可以解决this
问题。
function Person() { var that = this; that.age = 0; setInterval(function growUp() { // 回调引用的是`that`变量, 其值是预期的对象. that.age++; }, 1000); }
或者,可以创建绑定函数,以便将预先分配的this
值传递到绑定的目标函数(上述示例中的growUp()
函数)。
箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this
。因此,在下面的代码中,传递给setInterval
的函数内的this
与封闭函数中的this
值相同:
function Person(){ this.age = 0; setInterval(() => { this.age++; // |this| 正确地指向 p 实例 }, 1000); } var p = new Person();
与严格模式的关系
鉴于 this
是词法层面上的,严格模式中与 this
相关的规则都将被忽略。
function Person() { this.age = 0; var closure = "123" setInterval(function growUp() { this.age++; console.log(this.age);//NAN }, 1000); } var p = new Person(); function PersonX() { 'use strict' this.age = 0; var closure = "123" setInterval(()=>{ this.age++;
console.log(this.age);//正常的计数
}, 1000); } var px = new PersonX();
严格模式的其他规则依然不变.