本文实例讲述了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总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。
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()
中的第一个参数。
function person(name) { this.name = name; this.setname = function(name) { this.name = name; } } var person1 = new person("alice"); var person2 = {"name": "bruce"}; alert("person1: " + person1.name); // person1: alice person1.setname("david"); alert("person1: " + person1.name); // person1: david alert("person2: " + person2.name); // person2: bruce person1.setname.apply(person2, ["cindy"]); alert("person2: " + person2.name); // person2: cindy
apply()
将person1的方法应用到person2上,this也被绑定到person2上。
3、this优先级
(1)函数是否在new中调用,是的话this绑定到新创建的对象。
(2)函数是否通过call、apply调用,是的话this绑定到指定对象。
(3)函数是否在某个上下文对象中调用,是的话this绑定到该上下文对象。
(4)若都不是,使用默认绑定,若在严格模式下,绑定到undefined,否则绑定到全局对象。
4、this丢失的问题
eg1:
var person = { name: "alice", getname: function() { return this.name; } }; alert(person.getname()); // alice var getname = person.getname; alert(getname()); // undefined
当调用person.getname()
时,getname()
方法是作为person对象的属性被调用的,因此this指向person对象;
当用另一个变量getname来引用person.getname
,并调用getname()
时,是作为普通函数被调用,因此this指向全局window。
eg2:
<div id="div">正确的方式</div> <script> var getid = function(id) { return document.getelementbyid(id); }; alert(getid('div').innertext); </script> <div id="div">错误的方式</div> <script> var getid = document.getelementbyid; alert(getid('div').innertext); // 抛出异常 </script>
问题:第一段调用正常,但第二段调用会抛出异常。
原因:许多引擎的document.getelementbyid()
方法的内部实现中需要用到this,this本来期望指向的是document,当第一段代码在getelementbyid()
方法作为document对象的属性被调用时,方法内部的this确实是指向document的,而第二段代码中,用getid来引用document.getelementbyid
之后,再调用getid,此时就成了普通函数调用,函数内部的this指向了window,而不是原来的document。
解决:利用apply把document当作this传入getid函数,修正this。
<div id="div">修正的方式</div> <script> document.getelementbyid = (function(func) { return function() { return func.apply(document, arguments); }; })(document.getelementbyid); var getid = document.getelementbyid; alert(getid('div').innertext); // 抛出异常 </script>
更多关于javascript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《javascript常用函数技巧汇总》、《javascript错误与调试技巧总结》、《javascript数据结构与算法技巧总结》、《javascript遍历算法与技巧总结》及《javascript数学运算用法总结》
希望本文所述对大家javascript程序设计有所帮助。
如对本文有疑问, 点击进行留言回复!!
解决tomcat启动-Skipping unneeded JARs during scanning can improve startup time and JSP compilation time
网友评论