您好,欢迎来到飒榕旅游知识分享网。
搜索
您的当前位置:首页JavaScript中arguments和this对象用法分析

JavaScript中arguments和this对象用法分析

来源:飒榕旅游知识分享网

本文实例讲述了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()中的第一个参数。

    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程序设计有所帮助。

    Copyright © 2019- sarr.cn 版权所有

    违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

    本站由北京市万商天勤律师事务所王兴未律师提供法律服务