this
的基本概念
在 JavaScript 中,this
是函数执行时的上下文对象。它指向的是调用该函数的对象。通常,我们用 this 来访问该对象的属性和方法。
this
的指向通常依赖于函数的调用方式,而非函数定义时的上下文。这个特性是JavaScript中this
行为的核心所在。
this
的指向问题
1. 全局环境中的this
在全局环境中(不在任何函数或对象内部),this指向全局对象(在浏览器环境中是window,在node.js中是global)
js
console.log(this === window); // 在浏览器中输出 true
2. 函数中的this
当一个函数被直接调用时,this在非严格模式下指向全局对象(window),在严格模式下指向undefined
js
function regularFunction() {
console.log(this);
}
regularFunction(); // 非严格模式下指向 window,严格模式下为 undefined
// 演示严格模式下的情况
(function () {
"use strict";
regularFunction();
})();
3. 对象方法中的this
当函数作为对象的方法被调用时,this指向调用该方法的对象
js
var person = {
name: "John",
sayName: function () {
console.log(this.name);
}
};
person.sayName(); // 输出 "John",这里的 this 指向 person 对象
4. 构造函数中的this
使用new关键字(实例化)调用函数时,该函数被当作构造函数(类),this会指向新创建的对象实例
js
function Person(name) {
this.name = name;
this.sayHello = function () {
console.log("Hello, I'm " + this.name);
};
}
var john = new Person("John");
john.sayHello(); // 输出 "Hello, I'm John",这里 this 指向 john 实例
注意构造函数的执行方式
- 调用一个构造函数,他会立即创建一个对象
- 将新建的对象设置为函数中的this,在构造函数中可以使用this来引用新建的对象
- 逐行执行函数中的代码
- 将新建的对象作为返回值返回
5. 事件处理函数中的this
在DOM事件处理函数中,this通常指向触发事件的元素。
js
<button id="myButton">Click me</button>
<script>
var button = document.getElementById("myButton");
button.onclick = function () {
console.log(this); // 点击按钮时,这里的 this 指向按钮元素
//打印 :<button id="myButton">Click me</button>
};
</script>
6. 箭头函数中的this
箭头函数没有自己的this,它的this继承自外层作用域的this。
js
// 普通函数
function outerFunction() {
this.name = "Outer";
var innerFunction = function () {
console.log(this.name);
};
innerFunction();
}
// 箭头函数
function outerFunctionWithArrow() {
this.name = "Outer with Arrow";
var innerFunction = () => {
console.log(this.name);
};
innerFunction();
}
new outerFunction(); // 输出 undefined,因为 innerFunction 中的 this 指向全局对象,全局对象没有 name 属性
new outerFunctionWithArrow(); // 输出 "Outer with Arrow",箭头函数的 this 继承自 outerFunctionWithArrow 的 this
改变this
指向的方法
1.call()方法
- call 方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向。
- 语法: 函数名.call(要改变的 this 指向,要给函数传递的参数1,要给函数传递的参数2, ...)
- 使用 call 方法的时候:
-
- 1、会立即执行函数。
-
- 2、第一个参数是你要改变的函数内部的 this 指向
-
- 3、第二个参数是一个 数组,数组里面的每一项依次是向函数传递的参数(和call方法的主要区别点)
js
var obj = { name: 'Jack' }
function fn(a, b) {
console.log(this)
console.log(a)
console.log(b)
}
fn(1, 2)
fn.call(obj, 1, 2)
2、apply()方法
- apply 方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向
- 语法: 函数名.apply(要改变的 this 指向,[要给函数传递的参数1, 要给函数传递的参数2, ...])
- 使用 call 方法的时候:
-
- 1、会立即执行函数
-
- 2、第一个参数是你要改变的函数内部的 this 指向
-
- 3、第二个参数是一个 数组,数组里面的每一项依次是向函数传递的参数(和call方法的主要区别点)
js
var obj = { name: 'Jack' }
function fn(a, b) {
console.log(this)
console.log(a)
console.log(b)
}
fn(1, 2)
fn.apply(obj, [1, 2])
3、bind()方法
- bind 方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向
- 和 call / apply 有一些不一样,就是不会立即执行函数,而是返回一个已经改变了 this 指向的函数
- 语法: var newFn = 函数名.bind(要改变的 this 指向); newFn(传递参数)
js
var obj = { name: 'Jack' }
function fn(a, b) {
console.log(this)
console.log(a)
console.log(b)
}
fn(1, 2)
var newFn = fn.bind(obj)
newFn(1, 2)
-
- bind 调用的时候,不会执行 fn 这个函数,而是返回一个新的函数
-
- 这个新的函数就是一个改变了 this 指向以后的 fn 函数
-
- fn(1, 2) 的时候 this 指向 window
-
- newFn(1, 2) 的时候执行的是一个和 fn 一摸一样的函数,只不过里面的 this 指向改成了 obj