javascript 函数

arguments

  • 函数的实参被保存在一个类似数组的arguments对象中。
  • arguments变量只是 类数组对象“,并不是一个数组。称其为类数组对象是说它有一个索引编号和Length属性。尽管如此,它并不拥有全部的Array对象的操作方法。
  • 函数参数的默认值是undefined
  • 参数支持设置不同的默认值:function test(arg1, arg2 = 5) {}。
  • 原始参数(比如一个具体的数字)被作为传递给函数。
  • 对象参数,传递的是对象的应用。

常用:

  1. arguments[n]
  2. arguments.length
  3. arguments.callee(ECMAScript (ES5) forbids use of arguments.callee() in strict mode.)

递归函数

形式1: 通过使用函数名

function factorial(num){
    if(num <=1) {
        return 1;
    } else {
        return num * factoral(num-1);
    }
};

缺点:

var anotherFactorial = factorial;
factorial = null;
alert(anotherFactorial(4));  //VM367:5 Uncaught ReferenceError: factoral is not defined

形式2: 使用 arguments.callee

function factorial2(num){
    if(num <=1) {
        return 1;
    } else {
        return num * arguments.callee(num-1);
    }
};
var anotherFactorial = factorial2;
factorial2 = null;
alert(anotherFactorial(4));  //24

闭包与变量

  • 假设,函数A内部声明了个函数B,函数B引用了函数B之外的变量,并且函数A的返回值为函数B的引用。那么函数B就是闭包函数。
  • 内部函数可以访问定义在外部函数中的所有变量和函数,以及外部函数能访问的所有变量和函数。
  • 当内部函数生存周期大于外部函数时,由于内部函数可以访问外部函数的作用域,定义在外部函数的变量和函数的生存周期就会大于外部函数本身。

特点:

  1. 函数定义时的作用域链到函数执行时依然有效
  2. 闭包只取得包含函数中任何变量的最终值

形式1: 

function func1() {
    var result = new Array();
    for (var i = 0; i < 10 ;i++) {
        result[i] = function(){  // 外部函数变量得生命周期大于函数本身,闭包取到的总是外部函数最后的变量值 10 
            return i;
        }
    };
    return result;
};
res = func1();
res[1]();  //10
res[9]();  //10

形式2:

function func2() {
    var result = new Array();
    for (var i = 0; i < 10 ;i++) {
        result[i] = function(num){   
            return function(){
                return num;
            }
        }(i);  //  创建一个匿名函数并立即执行,将执行结果赋值给变量,匿名函数的参数复制i的值并又在它的闭包中保持
    };
    return result;
};
res = func2();
res[1]();  //1
res[9]();  //9

 this对象

this对象是在函数运行时基于函数执行环境绑定的:

  • 在全局函数中,this等于window。
  • 函数作为某个对象得方法调用时,this等于那个对象。
  • 匿名函数的执行环境具有全局性。

this等于window示例:

/*
 每个函数在被调用时,会自动获取两个特殊变量:this、arguments
 内部函数在搜搜这两个变量时只会搜索到其活动对象为止
 因此永远不可能直接访问外部函数中的这两个变量
*/
var name = "the Window";
var object = {
    name: "the Object",
    getNameFunc: function(){
        return function(){
            return this.name; 
        }
    }
};
alert(object.getNameFunc()());  //the Window

this等于Object, that等于this示例:

var name = "the Window";
var object = {
    name: "the Object",
    getNameFunc: function(){
        that = this;  //getNameFunc作为object的方法,在getNameFunc中this等于object
        return function(){
            return that.name;
        }
    }
};
alert(object.getNameFunc()());  //the Object

模仿块级作用域

javascript没有块级作用域:

function outputNumbers(count){
    for (var i=0; i < count; i++) ;  //do nothing
    alert(i); //块语句中定义的变量,在所在函数内都有效
}

模拟块级作用域:

function outputNumbers(count) {
    (function(){
        for (var i = 0; i<count; i++){
            alert(i);
        }
    })();  //定义匿名函数并立即执行,执行完后其定义的变量也会销毁
    alert(i);  //VM1909:7 Uncaught ReferenceError: i is not defined
}

访问私有变量

普通方式:

特点:

  1. 私有变量 name 在所有实例中都不同
  2. 每一个实例都会重新创建同样的一组私有方法(缺点)
function MyObject(){
    //私有变量
    var privateVariable = 10;
    //私有方法
    function privateFunction(){
        return false;
    }
    //特权方法
    this.publicMethod = function(){
        privateVariable++;
        return privateFunction();
    }
}
var test = MyObject();
test.publicMethod();  //访问私有变量

静态私有变量:

特点:

  1. 只有1个私有作用域
  2. 特权方法是在原型上定义的,因此所有实例都使用同一个函数
  3. 特权方法,作为一个闭包,总是保存着对包含作用域的引用
  4. 由1和3结合,所以任何一个实例改了私有变量,所有实例都感应变化
var Person;
(function(){
        var name = "";
        Person = function(value){
            name = value;
        },
        Person.prototype.getName = function(){
            return name;
        },
        Person.prototype.setName = function(value){
            name = value;
        }
    }
)();
var person1 = new Person("Nicholas");
alert(person1.getName());    //Nicholas
var person2 = new Person("Michael");
alert(person1.getName());  //Michael
alert(person2.getName());  //Michael

call()和apply()

  • call( thisArg[, arg1, arg2, ...]);     //参数列表
  • call( thisArg[, argArray ]);            //参数数组

两个函数内部的this指针,都会被赋值为 thisArg 对象,这可实现将函数作为另外一个对象的方法运行的目的。

obj = {
  x: 2,
  y: 5
};
function func(){
  return this.x * this.y;
}

func.call(obj);       // 10
func.apply(obj);      // 10
原文地址:https://www.cnblogs.com/licongyu/p/5621547.html