提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
this指向问题一直都是一个面试的热点问题那么就让我来学习一下吧。
一、this指向到底是什么?
this 总是(非严格模式下)指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境
动态绑定的,而非函数被声明时的环境;
二、this指向的几种方式
1.默认绑定
代码如下(示例):默认绑定 ,就是独立函数调用。但是要区分严格模式,在严格模式下就是undefined,非严格模式下this指向windo。
独立函数调用我们可以理解成函数有没有被绑定到某个对象上调用。
非严格模式 this指向 window
<script>
function foo() {
console.log(this);
// this 指向window
}
foo();
</script>
严格模式下 this指向 undefined
<script>
// 严格模式 "use strict"
"use strict"
function foo() {
console.log(this);
// this 指向window
}
foo();
</script>
2.隐式绑定
代码如下(示例):隐式绑定是另一种比较常见的调用方式,就是通过某个对象进行调用。
也就是说他是通过某个对象发起的函数调用,this指向这个对象
<script>
var info = {
name: "李四",
bar: function() {
console.log(this);
}
};
// 这种this指向就是 info
info.bar();
// 这种 this指向是 window 因为将函数赋值给fn变量
// 因为 fn()是一个函数 他是独立调用的 所以this指向window
var fn = info.bar();
fn();
// 总结 函数调用 前面写谁 this就指向谁 如果只是单一的调用那就指向window
</script>
3.new绑定 构造函数绑定
代码如下(示例):JavaScript中的函数可以当做一个类的构造函数来使用,也就是使用new关键字。
使用new关键字来调用函数
- 创建一个全新对象
- 这个this就会指向创建的空对象
- 给这个空对象身上追加属性
- 函数执行完毕,会自动的将this返回给函数的调用者
- 函数的调用者就是我们由构造函数创建的实例对象
<script>
// 1.声明函数
// 4.设置形参 接受实参
function Person(name, height, weight, addr) {
// new过程中 做了什么事情
// 5-1.创建一个全新对象
// 5-2.这个this就会指向创建的空对象
// 5-3.给这个空对象身上追加属性
// 5-4.函数执行完毕,会自动的将this返回给函数的调用者
// 5-5.函数的调用者就是我们由构造函数创建的实例对象
this.name = name;
this.height = height;
this.weight = weight;
this.addr = addr;
console.log(this);
console.log(height);
}
// 2.函数的调用
// 3.传入实参
var p1 = new Person("张三", 1.88, 60, "河南");
console.log(p1);
4. 显示绑定
代码如下(示例):明确的绑定了this指向的对象,就称为显示绑定
隐式绑定有一个前提
- 必须在调用的对象内部有一个对函数的引用(比如一个属性);
- 如果没有这样的引用,在进行调用时,会报找不到该函数的错误;
- 正是通过这个引用,间接的将this绑定到了这个对象上;
call和apply方法的使用
第一个参数都是相同的 都是表示this的指向 。
后面的参数 apply为数组 ,call为列表参数
<script>
function fn() {
console.log(this);
}
var obj = {
name: "obj",
};
// 函数调用方式
// this 默认指向window
fn();
// apply call 也可以调用函数 还可以改变this指向
// apply call 如果里面不写参数 那么还是默认指向window
// 如果添加参数 添加谁this就指向谁
fn.apply(obj);
fn.call(obj);
</script>
apply和call 添加参数
<script>
function fn(name, height, weight, addr) {
console.log(name, height, weight, addr);
}
fn("张三", 1.88, 70, "河南");
// apply 方法 调用函数
// 第一个参数 是this指向
// 第二个参数 是以一个数组的形式传入 数据传入到数组中
fn.apply("hello", ["李四", 1.70, 55, "南昌"]);
// call 方法 调用函数
// 第一个参数 是this指向
// 即第一个参数之后的参数依照列表的形式传入实参 将数据依次传入
fn.call("nihao", "王五", 1.50, 100, "上海")
</script>
bind的方法使用
bind()方法也可以改变this指向 ,传入实参和call方法相同
但是这个方法 不会调用函数 只会改变this指向
他会产生一个新函数 函数被称为 BF
<script>
function fn() {
console.log(this);
}
var obj = {
name: "张三"
}
//第三种方法 改变this指向 fn.bind() 传入实参和call用法相同
// 这个方法 不会调用函数 只会改变this的指向
// 并且产生一个新函数 新函数被称为 BF
var bar = fn.bind(obj, "李四", 188)
bar()
</script>
5.内置函数的绑定
代码如下(示例):
- 这些内置函数会要求我们传入另外一个函数;
- 我们自己并不会显示的调用这些函数,而且JavaScript内部或者第三方库内部会帮助我们执行;
<button>点击</button>
<script>
// 定制器 this指向window
setInterval(function() {
// console.log(this);window
}, 1000);
// 点击事件 this指向 button
var btn = document.querySelector("button");
btn.onclick = function() {
console.log(this);
}
var obj = {
name: "海绵宝宝"
}
// 高阶函数 高阶函数需要另一个函数作为参数
var arr = ["张三", "李四", "王五"];
arr.forEach(function(item, index, addr) {
// console.log(item, index, addr);
console.log(this);
}, obj)
</script>
6.箭头函数
代码如下(示例):箭头函数没有this指向 他会向外一层作用域去找 如果上一层没有那就一直向上一层查找一直到全局 要是还没找到那就指向 window
箭头函数有自己的作用域 但是没有this指向
<script>
// 全局 this
console.log(this);
var foo = () => {
// 箭头函数里面没有this
// 箭头函数有作用域 如果我们想输出一个变量
// 自己作用域里面没有 那向上一层作用域中查找
// 如果上一层没有 那就找到全局作用域
// 找到全局作用域 this 指向 window
console.log(this);
}
foo();
</script>
总结
提示:这里对文章进行总结:
- 默认绑定 this 指向 严格模式指向undefind ,非严格模式指向window
- 隐式绑定 this指向 this指向调用的对象
- new绑定 构造函数 this指向 this指向创建的新对象
- 显示绑定 this指向 this指向自己传入的对象
- 内置函数的绑定 this指向 this指向因情况而定 详情请看上面解释
- 箭头函数 this指向 箭头函数没有this指向