JavaScript中arguments和this对象用法分析

在函数内部有两个特殊的对象 : arguments和this。

1、arguments对象

js函数不介意定义多少参数,也不在乎传递进来多少参数,也就是说,即使定义的函数只接收2个参数,在调用时候也未必传递2个参数,因为js的函数参数在内部使用一个数组表示的,在函数体内可以通过arguments对象访问此参数数组。因此,js函数可以不显式地使用命名参数。

当函数被调用时,传入的参数将保存在arguments类数组对象中,通过arguments可以访问所有该函数被调用时传递给它的参数列表。

arguments是一个类数组对象,因为arguments可以通过方括号语法访问每一个元素,且拥有一个length属性,但它缺少所有的数组方法,因此并不是一个真正的数组。

使用arguments可以实现一个求和函数:

function add() { var sum = 0; for (var i = 0, len = arguments.length; i < len; i++) sum += arguments[i]; return sum; }

虽然arguments的主要用途是保存函数参数,但这个对象还有一个callee属性,该属性是一个指针,指向拥有这个arguments对象的函数。

使用arguments.callee属性可以实现一个阶乘函数:

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

注意:

在严格模式下,不能使用arguments.callee属性,也不能对arguments对象赋值,更不能用arguments对象跟踪参数的变化。

可以使用命名函数表达式来达成同样的效果:

var factorial = (function func(num) { if (num <= 1) return 1; else return num * func(num - 1); ));

由于js函数没有签名(定义接受的参数的类型和数量),js函数没有重载,对于同名函数,后定义的函数会覆盖先定义的函数。当然,通过检查传入的参数的类型和数量并做出不同的反应,可以模仿方法的重载。

2、this对象

与别的语言不同,JavaScript的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。

this是执行上下文的一个属性,其值在进入上下文时确定,且在上下文运行期间永久不变。

this 是动态绑定的,即在运行期绑定。

this可以是全局对象,当前对象或任意对象,取决于函数的调用方式。函数的调用方式有以下几种:作为普通函数调用,作为对象方法调用,作为构造函数调用,使用call()和apply()调用。

(1)作为普通函数调用

当函数不作为对象的属性被调用,即直接被调用时,this会被绑定到全局对象。在浏览器的JavaScript里,该全局对象是window对象。

var name = "Alice"; function getName (name) { return this.name; } alert(getName()); // 输出:Alice var name = "Alice"; var obj = { name: 'Bruce', getName: function(name) { return this.name; } }; var getName = obj.getName(); alert(getName()); // 输出:Alice

以上两个实例中,this都被绑定到了全局对象。

var firstname = "A"; var lastname = "B"; var person = { firstname : "Alice", lastname : "Bruce", setName : function(firstname, lastname) { var setFirstName = function(firstname) { this.firstname = firstname; }; var setLastName = function(lastname) { this.lastname = lastname; }; setFirstName(firstname); setLastName(lastname); } }; person.setName("Cindy", "David"); alert(firstname);//Cindy alert(lastname);//David alert(person.firstname);//Alice alert(person.lastname);//Bruce

问题:在函数内部定义的函数,this也可能会指向全局,而希望的是内部函数的this绑定到外部函数对应的对象上。

原因:内部函数永远不可能直接访问外部函数中的this变量。

解决:在外部函数体中,要进入内部函数时,将this保存到一个变量中,再运用该变量。

var firstname = "A"; var lastname = "B"; var person = { firstname: "Alice", lastname: "Bruce", setName: function(firstname, lastname) { var that = this; var setFirstName = function(firstname) { that.firstname= firstname; }; var setLastName = function(lastname) { that.lastname= lastname; }; setFirstName(firstname); setLastName(lastname); } }; person.setName("Cindy", "David"); alert(firstname);//A alert(lastname);//B alert(person.firstname);//Cindy alert(person.lastname);//David

(2)作为对象方法调用

当函数作为对象方法调用时,this会被绑定到当前对象。

var firstname = "A"; var lastname = "B"; var person = { firstname : "Alice", lastname : "Bruce", setName : function(firstname, lastname) { this.firstname = this.firstname + firstname; this.lastname = this.lastname + lastname; } }; person.setName("Cindy", "David"); alert(firstname);//A alert(lastname);//B alert(person.firstname);//AliceCindy alert(person.lastname);//BruceDavid

this被绑定到了当前对象,即person对象。

(3)作为构造函数调用

JavaScript中没有类,但可以从构造器中创建对象,同时也提供了new运算符,使得构造器看起来更像一个类。

利用构造函数创建新对象时,可以将this来指向新创建的对象,避免函数中的this指向全局。

var name = "Alice"; function Person(name) { this.name = name; } var person = new Person("Bruce"); alert(name);//Alice alert(person.name);//Bruce

利用构造函数创建新对象person,this指向了person。

用new调用构造器时。还要注意一个问题,若构造器显式返回了一个object类型的对象,构造器返回的结果将是这个对象,而不是this。

function Person() { this.name = "Alice" return { name: "Bruce" } } var person = new Person(); alert(person.name);//Bruce

(4)call()和apply()调用

call()和apply()切换函数执行的上下文环境,即this绑定的对象;this指向的是apply()和call()中的第一个参数。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/3c3c2c5739a06b2e21f6b6e53befb132.html