1.函数简要说明
首先简单说一下,对象中都有__ptoto__属性,而函数中也有__proto__,因此可以看出函数也是对象。函数其实是Function构造函数的实例对象。即:如下的addFun1的调用效果和addFun2的调用效果是一样的。
addFun1:
function addFun1(num1,num2) {
return num1+num2;
}
console.log(addFun1(20,30))
addFun2
let addFun2=new Function("num1","num2","return num1+num2")
console.log(addFun2(20,30));
可以打印一个函数看看内部结构如下:
可以看见,apply()、call()、bind() 都不在函数中,而是在指向的原型对象中。
明确函数中的this的指向:
- 普通的函数中this指向的是window—严格模式下,如果不使用window.函数名()调用的话,那么this是undefined
- 构造函数中的this 一般指向的是实例对象
- 方法中的this 指向的是实例对象
- 原型中的方法的this 指向的也是实例对象
- 定时器中的this指向的是window
2.apply()
apply的主要作用就是在调用的时候改变this的当前指向
使用方法:apply(对象,[参数1,参数2,…])
注意事项:当第一个参数不传或者传null时,对应函数或者方法内的this指向不改变。对应函数或者方法需要的参数,以数组的形式传进去。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
//apply 和call 都是改变函数中的this指向
//
//
function f1(x,y) {
console.log("嘿~两数之和为:"+(x+y)+"当前this的指向为:↓");
console.log(this);
}
f1(10,20);
console.log("===========分割线=====================");
//使用apply
console.log("使用apply,第一个参数不传,或者为null的时候:");
f1.apply(null,[10,20]);
//使用apply
console.log("使用apply,第一个参数传入对象的时候:");
let obj={
name:"张三",
sex:"男",
age:10
}
f1.apply(obj,[10,20]);
console.log("==========================对象中的方法this指向的改变========================");
function Person(name,age) {
this.name=name;
this.age=age;
}
Person.prototype.sayHi=function () {
console.log("当前的sayHi的this指向:↓");
console.log(this);
}
function Student(score) {
this.score=score;
}
let stu=new Student(100);
let per1=new Person("张三",20);
console.log("=======per的sayHi方法使用apply");
per1.sayHi.apply(stu);
</script>
</body>
</html>
3.call()
call的主要作用也是在调用的时候改变this的当前指向。在实现继承的时候,通过借用构造函数实现继承的方式中,就用到这个方法。
使用方法:call(对象,参数1,参数2,…)
注意事项:当第一个参数不传或者传null时,对应函数或者方法内的this指向不改变。对应函数或者方法需要的参数,接在对象后面一次传进去。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
//apply 和call 都是改变函数中的this指向
//
//
function f1(x,y) {
console.log("嘿~两数之和为:"+(x+y)+"当前this的指向为:↓");
console.log(this);
}
f1(10,20);
console.log("===========分割线=====================");
//使用call
console.log("使用call,第一个参数不传,或者为null的时候:");
f1.call(null,10,20);
//使用call
console.log("使用call,第一个参数传入对象的时候:");
f1.call(obj,10,20);
console.log("==========================对象中的方法this指向的改变========================");
function Person(name,age) {
this.name=name;
this.age=age;
}
Person.prototype.sayHi=function () {
console.log("当前的sayHi的this指向:↓");
console.log(this);
}
function Student(score) {
this.score=score;
}
let stu=new Student(100);
let per1=new Person("张三",20);
console.log("=======per的sayHi方法使用call");
per1.sayHi.call(stu);
</script>
</body>
</html>
4.bind()
前面说了apply和call 都是在调用函数或者方法的时候改变this指向,而 bind只是把函数复制了一份,在复制的时候改变this的指向。在复制的时候可以传入参数,也可以在调用的时候传参。
使用方法:bind(对象,参数1,参数2,…)
注意事项:当第一个参数不传或者传null时,对应函数或者方法内的this指向不改变。对应函数或者方法需要的参数,可以接在对象后面一次传进去,也可以在调用的时候再传参
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
//前文说了apply和call 都是在调用函数或者方法的时候改变this指向
//
//那么 bind作用是什么呢
//由下面的例子可以看出 bind只是把函数复制了一份,在复制的时候改变this的指向。在复制的时候可以传入参数,也可以在调用的时候传参
function f1(x,y) {
console.log("两者之和:"+(x+y));
console.log("当前的this指向为↓:");
console.log(this);
}
console.log("使用bind====只传入null===这个时候的this指向还是window=================");
let ff=f1.bind(null);
ff();
console.log("使用bind,传入一个对象,但是不传递任何函数需要的参数,这个时候的this就是传递的对象===================");
function Person(age) {
this.age=age;
}
let per1=new Person(20);
let ff2=f1.bind(per1);
ff2(3,5);
console.log("使用bind,传入一个对象,传递函数需要的参数,这个时候的this也是传递的对象===================");
let ff3=f1.bind(per1,3,5);
ff3();
</script>
</body>
</html>