一、this
解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象我们称为函数执行的 上下文对象。
根据函数的调用方式的不同,this会指向不同的对象:【重要】
- 1.以函数的形式调用时,this永远都是window。比如
fun();
相当于window.fun();
- 2.以方法的形式调用时,this是调用方法的那个对象
- 3.以构造函数的形式调用时,this是新创建的那个对象
- 4.使用call和apply调用时,this是指定的那个对象
情况一:以函数形式调用
//情况一:以函数形式调用
function fun() {
console.log(this);
console.log(this.name);
}
var obj1 = {
name: "smyh",
sayName: fun
};
var obj2 = {
name: "vae",
sayName: fun
};
var name = "全局的name属性";
//以函数形式调用,this是window
fun(); //可以理解成 window.fun()
//this指向的是window对象,所以 this.name 指的是全局的name。
情况二:以方法的形式调用
//情况二:以方法的形式调用
function fun() {
console.log(this);
console.log(this.name);
}
var obj1 = {
name: "smyh",
sayName: fun
};
var obj2 = {
name: "vae",
sayName: fun
};
var name = "全局的name属性";
//以方法的形式调用,this是调用方法的对象
obj2.sayName();
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YfPy0NlC-1595184166008)(C:\Users\ya琪琦儿\AppData\Roaming\Typora\typora-user-images\1595174265374.png)]
情况三:以构造函数形式进行调用
//情况三:以构造函数形式进行调用
function Student(name){
this.name = name; //this指的是构造函数中的对象实例
this.grade = function(){
console.log(this.name + "是二班的");
}
}
var student1 = new Student("小米"); //自定义对象
var student2 = new Student("大米");
情况四:以call和apply形式进行调用
call和apply是用来改变this的指向
//情况四:
<script type="text/javascript">
var student1 = {
name:"小米",
age:19,
hobby:function(){
console.log(this.name + "喜欢跳舞")
for (var i=0; i<arguments.length;i++) {
console.log(this.name + arguments[i]);
}
}
}
var student2 = {
name:"大米",
}
var fn = student1.hobby
student1.hobby(); //此时this指向的是student1
fn(); //此时this指向window
//改变this的指向
fn.call(student2) //此时this指向的是student2
// fn.apply(student2) //此时this指向的是student2
</script>
改变this的指向:
call和apply
call和apply:通过call和apply可以在调用方法的时候改变this的指向。(例子见上述情况四)
fn.call(student2)
fn.apply(student2)
call和apply的区别:
传参的不同。
student1.hobby.call(student2,"唱歌","跳舞","rap"); //传参是一个一个依次按顺序传入
student1.hobby.apply(student2,["唱歌","跳舞","rap"]); //传参是以数组形式传入:a——>array
bind
利用bind绑定对象,改变this的指向
var fn = function(){
console.log(this)
console.log(this.name+"喜欢打篮球!")
for(var i = 0;i<arguments.length;i++){
console.log(this.name+"喜欢"+arguments[i])
}
}.bind(student)
fn() //this--->学生
箭头函数
ES6中的箭头函数并不会使用上面四条标准的绑定规则,而是会继承外层函数调用的this绑定(无论this绑定到什么)。(后续回进行补充…)
<script type="text/javascript">
console.log(this)
var student = {
name:"学生",
//下面这个就是箭头函数
like:()=>{
console.log(this) //这里的this并不是指向student,而是取决于外层函数
console.log(this.name)
console.log(this.name+"喜欢乒乓球")
}
}
</script>
二、类数组arguments
在调用函数时,浏览器每次都会传递进两个隐含的参数:
- 1.函数的上下文对象 this
- 2.封装实参的对象 arguments
function fn() {
console.log(arguments);
console.log(typeof arguments);
}
fn();
arguments是一个类数组对象,它可以通过索引来操作数据,也可以获取长度。
arguments代表的是实参。在调用函数时,我们所传递的实参都会在arguments中保存。
arguments只在函数中使用。
1、返回函数实参的个数:arguments.length
fn(2,4);
fn(2,4,6);
fn(2,4,6,8);
function fn(a,b) {
console.log(arguments);
console.log(fn.length); //获取形参的个数
console.log(arguments.length); //获取实参的个数
console.log("----------------");
}
结果为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JpabvkiW-1595184166009)(C:\Users\ya琪琦儿\AppData\Roaming\Typora\typora-user-images\1595176566028.png)]
2、返回正在指向的函数:arguments.callee
callee这个属性对应一个函数对象,就是当前正在指向的函数对象
function fun() {
console.log(arguments.callee == fun); //输出结果为true
}
fun("hello");
在使用函数递归调用时,推荐使用arguments.callee代替函数名本身。
3、利用auguments修改元素
arguments是伪数组,是因为:arguments可以修改元素,但不能改变数组的长短。
fn(2,4);
fn(2,4,6);
fn(2,4,6,8);
function fn(a,b) {
arguments[0] = 99; //将实参的第一个数改为99
arguments.push(8); //此方法不通过,因为无法增加元素,不能改变数组的长度
}
arguments是伪数组,是因为:arguments可以修改元素,但不能改变数组的长短。
fn(2,4);
fn(2,4,6);
fn(2,4,6,8);
function fn(a,b) {
arguments[0] = 99; //将实参的第一个数改为99
arguments.push(8); //此方法不通过,因为无法增加元素,不能改变数组的长度
}