JavaScript 中 this 指向详解

简介: JavaScript 中 this 指向详解

使用 JavaScript 开发的时候,很多开发者多多少少会被 this 的指向搞蒙圈,但是实际上,关于 this 的指向,记住最核心的一句话:哪个对象调用函数,函数里面的 this 指向哪个对象

this的几种模式:

函数调用下,this 指向 window ,调用方法没有明确对象的时候,this 指向 window,如 setTimeout、匿名函数等;

构造函数调用模式下,this 指向被构造的对象;

apply,call,bind 调用模式下,this 指向第一个参数;

箭头函数,在声明的时候绑定this,而非取决于调用位置;

严格模式下,如果 this 没有被执行环境(execution context)定义,那 this是 为undefined;

下面我们针对这几种情况,举例并说明原理:

1. 方法调用模式

// 声明位置
var test = function(){
  console.log(this.x)
} 
var x = "2";
var obj = {
  x:"1",
  fn:test,
}
// 调用位置
obj.fn(); // 1
test(); // 2

以上代码,可以看到,this 指向调用它所在方法的对象,test 方法在 obj 对象下,所以 this 指向 obj,test 在window 对象下,所以 this 指向 window。也可以看出来:this和声明位置无关,和调用位置有关。

但是下面这个情况得注意

let obj1={
  a:222
};
let obj2={
  a:111,
  fn:function(){
    console.log(this.a);
  }
}
obj1.fn = obj2.fn;
obj1.fn(); // 222

这个不难理解,虽然 obj1.fn 是从 obj2.fn 赋值而来,但是调用函数的是obj1,所以 this 指向 obj1。

2. 函数调用模式

var a = 1;
function fn1(){
  console.log(this.a); // 1
}
fn1();
window.b = 2;
function fn2(){
  console.log(this.b); // 2
}
fn2();
//可以理解为 window.fn();

匿名函数,setTimeout:

(function(){
  console.log(this); // window
})();
setTimeout(() => {
  console.log(this); // window
}, 0);
setTimeout(function(){
  console.log(this); // window
}, 0);

3. 构造函数模式

var flag = undefined; 
function Fn(){
  flag = this;
}    
var obj = new Fn();
console.log(flag === obj); // true

这个 this 指向 obj,内部原理还是用 apply 把 this 指向obj的,回忆下JavaScript中 new 一个对象过程详解

4. call、apply、bind

call 和 apply 的作用,完全一样,唯一的区别:参数;

call 接收的参数不固定,第一个参数是函数体内 this 的指向,第二个参数以下是依次传入的参数。

apply接收两个参数,第一个参数也是函数体内 this 的指向。第二个参数是一个集合对象(数组或者类数组)

var obj = {
  name:'111',
  getName:function(){
    console.log(this.name)
  }
};
var otherObj = {
  name:'222',
};
var name = '333';
obj.getName();               // 111
obj.getName.call();          // 333
obj.getName.call(otherObj);  // 222
obj.getName.apply();         // 333
obj.getName.apply(otherObj); // 222
obj.getName.bind(this)();    // 333
obj.getName.bind(otherObj)();// 222

5. 箭头函数

关于 ES6 中的箭头函数,官方的解释是:

箭头函数里面的 this 是上下文( context ), 外部作用域的 this 就是箭头函数内的 this。


判断箭头函数的 this:

技巧:它的外层没有函数,this 是 window;外层有函数,看外层函数的 this 是谁,它的 this 就是谁。

外层函数可能是常规函数可能是箭头函数,判断外层的 this 要根据函数种类用不同方法:

外层函数是常规函数就看外层函数是被谁调用的;

外层是箭头函数就根据刚才说的技巧来判断;

let obj={
  a:222,
  fn:function(){    
    setTimeout(()=>{console.log(this.a)});
  }
};
obj.fn(); // 222
var name = 'window'; 
var A = {
  name: 'A',
  sayHello: () => {
    console.log(this.name)
  }
}
A.sayHello(); // 输出的是window,根据刚才讲的规则就可以判断
// 那如何改造成永远绑定A呢:
var name = 'window'; 
var A = {
  name: 'A',
  sayHello: function(){
    var s = () => console.log(this.name)
    return s//返回箭头函数s
  }
}
var sayHello = A.sayHello();
sayHello();// 输出A 
  • call() 、apply() 、 bind() 方法对于箭头函数来说只是传入参数,对它的 this 毫无影响;
  • 考虑到 this 是词法层面上的,严格模式中与 this 相关的规则都将被忽略(忽略是否在严格模式下的影响);
var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true
var obj = {foo: foo};
console.log(foo.call(obj) === globalObject); // true
foo = foo.bind(obj);
console.log(foo() === globalObject); // true

6. 严格模式

非严格模式下,this 默认指向全局对象 window;

// 非严格模式
function f1(){
  return this;
}
console.log(f1() === window); // true

严格模式下, this 为undefined;

// 严格模式
"use strict";
var fn2 = function(){
  return this
}    
console.log(fn2() == undefined); // true
相关文章
|
9月前
|
JavaScript 前端开发
javascript中的this
javascript中的this
|
9月前
|
JavaScript
JS中改变this指向的六种方法
JS中改变this指向的六种方法
|
8月前
|
自然语言处理 JavaScript 前端开发
在JavaScript中,this关键字的行为可能会因函数的调用方式而异
【6月更文挑战第15天】JavaScript的`this`根据调用方式变化:非严格模式下直接调用时指向全局对象(浏览器为window),严格模式下为undefined。作为对象方法时,`this`指对象本身。用`new`调用构造函数时,`this`指新实例。`call`,`apply`,`bind`可显式设定`this`值。箭头函数和绑定方法有助于管理复杂场景中的`this`行为。
70 3
|
7月前
|
JavaScript
js 【详解】函数中的 this 指向
js 【详解】函数中的 this 指向
57 0
|
7月前
|
JavaScript 前端开发
|
9月前
|
JavaScript 前端开发
js中改变this指向、动态指定函数 this 值的方法
js中改变this指向、动态指定函数 this 值的方法
|
8月前
|
JavaScript
js -- 函数总结篇,函数提升、动态参数、剩余参数、箭头函数、this指向......
js -- 函数总结篇,函数提升、动态参数、剩余参数、箭头函数、this指向......
|
8月前
|
JavaScript 前端开发
JS中如何使用this方法
JS中如何使用this方法
33 0
|
9月前
|
自然语言处理 JavaScript 前端开发
在JavaScript中,this关键字的行为可能会因函数的调用方式而异
【5月更文挑战第9天】JavaScript中的`this`关键字行为取决于函数调用方式。在非严格模式下,直接调用函数时`this`指全局对象,严格模式下为`undefined`。作为对象方法调用时,`this`指向该对象。用`new`调用构造函数时,`this`指向新实例。通过`call`、`apply`、`bind`可手动设置`this`值。在回调和事件处理中,`this`可能不直观,箭头函数和绑定方法可帮助管理`this`的行为。
51 1
|
9月前
|
JavaScript 前端开发
深入探索JavaScript:如何改变this的指向
深入探索JavaScript:如何改变this的指向
73 2

热门文章

最新文章

  • 1
    当面试官再问我JS闭包时,我能答出来的都在这里了。
    40
  • 2
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    27
  • 3
    Node.js 中实现多任务下载的并发控制策略
    32
  • 4
    【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
    26
  • 5
    【JavaScript】深入理解 let、var 和 const
    49
  • 6
    【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
    47
  • 7
    【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
    54
  • 8
    【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
    57
  • 9
    如何通过pm2以cluster模式多进程部署next.js(包括docker下的部署)
    72
  • 10
    【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
    55