JavaScript的arguments和this对象
(以下所有内容仅用以记录学习过程中的个人理解,如有错误欢迎指出)
JS在调用函数时,每次都会传递进来两个隐含的参数对象:arguments和this。
1. arguments对象
JS的函数不在乎定义多少/传递多少参数,也就是说,即使定义的函数没有参数,在调用时也能传递进参数。
但与之同时要如何拿到传递进来的参数呢,答案就是靠arguments。
因为JS中所传递的函数参数在其内部是通过arguments这一类数组对象保存表示的,因此在函数内可以通过它来访问参数数组。
arguments可以通过[ ]
访问每一个元素,而且拥有length属性。
function fun(){
console.log(arguments.length); //length = 3,传递进参数的长度
console.log(arguments[0]); //arguments[0] = hello world
console.log(typeof arguments[0]); //string
}
fun("hello world",123,true);
但是arguments不能使用数组的方法,所以它并不是一个真正的数组
function fun(){
console.log(arguments instanceof Array);
console.log(Array.isArray(arguments));
//false,不是数组
}
arguments还有一个callee属性,这个属性是一个指针,对应一个函数对象,就是当前拥有这个arguments的函数对象。
function fun(){
console.log(arguments.callee);
console.log(arguments.callee == fun); //true
}
/* callee输出该函数对象
ƒ fun(){
console.log(arguments.callee);
console.log(arguments.callee == fun);
}
*/
2. this对象
JS中的this是一个执行上下文的属性,它的值是在运行期动态绑定的,在进入上下文时确定且永久不变。
根据调用方式的不同,this可以是全局对象/当前对象/任意对象,它有以下四种调用方式:
2.1 作为普通函数调用
当this作为普通函数调用时,this会被绑定到全局对象。
var name = "Tom";
function getName (name) {
return this.name;
}
console.log(getName()); //Tom
this的这种调用方式,会与闭包有所关联,日后再说。
2.2 作为对象方法调用
当this作为对象方法调用时,this会被绑定到当前对象。
var person = {
setName: function(firstname, lastname) {
this.firstname = firstname;
this.lastname = lastname;
console.log(person.firstname); //Alice
console.log(person.lastname); //Bob
}
};
person.setName("Alice", "Bob");
如上例,this被绑定到了当前的这一person对象。
2.3 作为构造函数调用
当this作为对象方法调用时,this会被绑定到新创建对象。
function Person(name) {
this.name = name;
}
var person = new Person("Alice");
console.log(person.name); //Alice
如上例,this被绑定到了新创建的person对象。
2.4 call()和apply()调用
当this使用 call() 和 apply() 调用时,this会被绑定到指定对象,即call()和apply()的第一个参数。
function Person(name) {
this.setName = function(name) {
this.name = name;
}
}
var person1 = new Person();
var person2 = { name: "Bob" };
console.log(person2.name); //Bob
person1.setName.call(person2, "Jack");
console.log(person2.name); //Jack
var person3 = { name: "Sam" };
console.log(person3.name); //Sam
person1.setName.apply(person3, ["Tom"]);
console.log(person3.name); //Tom
如上例,根据call()和apply()第一个参数指定的对象不同,call()将person1的setName方法的this绑定到了person2上,apply()将person1的setName方法的this绑定到了person3上。