Function

Javascript设计得最出色的就是他的函数的实现。 函数就是对象,唯一与众不同的是它可以被调用。(没有重载)

函数定义

函数声明

function 函数名(形式参数) {
    函数功能实现
}

函数表达式

var 函数名 = function [函数名](形式参数) {
    函数功能实现
}

此处函数名可省略,省略后被称为匿名函数表达式。

使用Function构造函数

var 函数名 = new Function(形式参数, 函数体);

传入值都是字符串类型,最后一个参数始终被看成函数体。 不推荐使用:

函数声明提升

javascript引擎在执行前的解析阶段有一个“函数声明提升”的过程。把函数声明提升到作用域的顶部。
当然变量声明也会提升,但函数声明具有比变量声明更高的优先级。

(function(){
    var test;
    function test() {console.log('test')};。
    console.log(typeof test);   // function
})();

(function(){
    function test() {console.log('test')};
    var test;
    console.log(typeof test);   // function
})()

除了函数声明,后面两种定义方式都不会有提升效果

函数作用域

ES6之前js只有函数作用域,没有块作用域。ES6之前函数作用域是最常见的作用域单元,ES3开始就有块级作用域。

try {
    throw undefined;
} catch (a) {
    a = 2;
    console.log( a );
}
console.log( a );

闭包

闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。 函数定义内部可以自由访问把它嵌套在其中的父函数的参数与变量。

函数内部属性

arguments

arguments是个类数组对象(拥有数值索引和length属性),包含这传入函数中的所有参数。

arguments.callee

同时还有一个callee属性,是一个指向拥有这个arguments对象的函数。 在 ECMAScript 第五版 (ES5) 的 严格模式 中禁止使用 arguments.callee()。

arguents.caller[已经废弃]

使用arguments.callee.caller代替

this

this判定的优先级

  1. 函数是否在new中调用(new绑定)?如果是的话this绑定的是新创建的对象。

    function foo() { 
        console.log(this.a);
    }
    var o= {a: 3};
    var fooBind = foo.bind(o)
    fooBind(); // 3
    new fooBind(); // undefined
  2. 函数是否通过call、apply(显式绑定)或者bind(硬绑定)调用?如果是的话,this绑定的是 指定的对象。

  3. function foo() { 
        console.log(this.a);
    }
    var o= {a: 3};
    var fooBind = foo.bind(o)
    fooBind(); // 3
    fooBind.call({a: 4}); // 3
  4. 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this绑定的是那个上 下文对象。

  5. 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到 全局对象。

  6. 例外

    1. 如果你把 null 或者 undefined 作为 this 的绑定对象传入 call、apply 或者 bind,这些值在调用时会被忽略,实际应用的是默认绑定规则**

      function foo(p1,p2) {
          this.val = p1 + p2;
      }
      var bar = foo.bind( null, "p1" );
      var baz = {
          bar: bar
      };
      baz.bar( "p2" );
      console.log(baz.val); // undefined
      console.log(window.val); //p1p2

      总是使用 null 来忽略 this 绑定可能产生一些副作用。如果某个函数确实使用了 this(比如第三方库中的一个函数),那默认绑定规则会把 this 绑定到全局对象(在浏览 器中这个对象是 window),这将导致不可预计的后果(比如修改全局对象)。

      可以使用Object.create(null),它和 {} 很像,但是并不会创建 Object.prototype 这个委托,所以它比 {}“更空。

    2. 间接引用

      function foo() { 
          console.log(this.a);
      }
      var a = 2;
      var o = { a: 3, foo: foo }; 
      var p = { a: 4 };
      o.foo(); // 3
      (p.foo = o.foo)(); // 2
    3. 软绑定:

      Function.prototype.softBind = function(obj) {
          var fn = this;
          // 捕获所有 curried 参数
          var curried = [].slice.call(arguments, 1);
          var bound = function() {
              return fn.apply(
                  (!this || this === (window || global)) ? obj : this,
                  curried.concat.apply(curried, arguments)
               ); 
          };
          bound.prototype = fn.prototype;
          return bound; 
      };

函数属性

函数方法

函数递归

一个函数在自身内部调用自身: