函数内部this的指向
调用的方式不同,决定了this的指向不同。
调用方式 this指向
普通函数调用 window
构造函数调用 实例对象,原型对象里方法中的this也指向实例对象
对象方法调用 该方法所属对象
事件绑定方法 绑定事件对象
定时器函数 window
立即执行函数 window
改变函数内部this的指向
常用的有call()、apply()、bind()三种方法
call方法
1、call可以调用函数,改变函数内的this指向,参数形式用逗号隔开
let people = {
name: '刘德华'
}
function fn(a, b, c) {
console.log(this); // this指向的是people
console.log(a, b, c)
}
fn.call(people, 1, 2, 3);
2、call可以实现继承
function Father(uname, age, sex) {
this.uname = uname;
this.age = age;
this.sex = sex;
}
function Son(uname, age, sex) {
Father.call(this, uname, age, sex);
}
let son = new Son('刘德华', 18, '男');
console.log(son); // 实例对象继承了父类构造函数的属性
apply方法
apply可以调用函数,改变函数内的this指向(),参数以数组的形式
let people = {
name: '刘德华'
}
function fn() {
console.log(this); // this指向的是people
}
fn.apply(people, ['apple', 'banana']);
利用apply求值
let arr = [10, 2, 45, 77, 60]; let max = Math.max.apply(null, arr);
let min = Math.min.apply(null, arr);
console.log(max);
console.log(min);
bind方法
bind方法不会调用函数,但会改变函数内部this的指向,返回由指定的this值和初始化参数的原始拷贝
let people = {
name: '刘德华'
}
function fn() {
console.log(this); // this指向的是people
}
let f = fn.bind(people);
f()
Example:
<button>点击</button>
let btn = document.querySelector('button');
btn.onclick = function () {
this.disabled = true; // 方法一,外部保存this
// let self = this;
// setTimeout(function() {
// // this.disabled = false; // 错误: 定时器函数里的this,指向的是window
// self.disabled = false;
// }, 3000);
// 方法二,利用bind,修改定时器函数里的this
// setTimeout(function() {
// this.disabled = false;
// }.bind(this), 3000);
// 方法三,利用箭头函数
// setTimeout(() => {
// this.disabled = false;
// }, 3000);
};
call、apply和bind的总结
相同点:都可以改变函数内部this的指向
区别点:
1、call和apply会调用函数,并且改变函数内部this的指向
2、call和apply传递的参数不一样,call传递参数aru1, aru2,...的形式;apply必须数组形式
3、bind不会调用函数,参数跟call一样
主要应用场景:
1、call经常做继承
2、apply经常更数组有关系,比如接触数学对象实现数组的最大值、最小值
3、bind不调用函数,改变this指向,比如改变定时器内部的this指向
递归函数
利用递归求阶乘,1*2*3*4...*n
function fn(n) {
if (n == 1) return 1;
return n * fn(n - 1);
}
console.log(fn(9));
利用递归求斐波那契数列,0、1、1、2、3、5、8、13、21、34、……这个数列从第3项开始,每一项都等于前两项之和
function fb(n) {
if (n == 1 || n == 2) return 1;
return fb(n - 1) + fb(n - 2);
}
console.log(fb(9));