😄
前端学习
  • 👋Welcome
  • 📖前端基础
    • HTML
      • 基础知识
      • 进阶知识
      • HTML5
    • CSS
      • 基础知识
      • 进阶知识
      • CSS 专题
        • CSS 选择器
        • CSS 布局
        • CSS 动画
        • CSS 画图
        • 响应式方案
        • CSS BEM 规范
        • CSS 案例
    • JavaScript
      • 基础知识
      • 进阶知识
      • 常用内置对象
        • Array 对象
        • String 对象
        • Number 对象
        • Boolean 对象
        • Math 对象
        • Date 对象
        • RegExp 对象
        • Object 对象
      • JS 专题
        • 数据类型
        • 原型链/继承
        • 对象赋值与拷贝
        • this 的指向
        • 异步操作
        • 模块化
        • 设计模式
    • 浏览器
      • 浏览器模型
      • 事件
      • 位置属性
      • Web 缓存
      • 本地存储
    • 综合内容
      • 前端跨域
      • 登录鉴权
      • 文件上传与下载
  • 🏗️前端框架
    • Vue.js
      • 基础知识
      • Vue 组件通信
      • Vuex 使用指南
      • Vue 动画
      • 静态网站框架 VuePress
    • React.js
      • 基础知识
      • 组件通信
  • 📦计算机基础/后端
    • 图解计算机网络
    • HTTP/HTTPS
    • TCP/UDP
    • Node.js
    • MongoDB
  • 🛠️开发工具
    • 版本控制工具-Git
      • git submodule
    • 构建工具-Webpack
    • 错误监控工具-Sentry
    • 单元测试工具-Jest
    • 包管理工具-NPM
    • 代码编辑器-VSCode
  • 🤔专题内容
    • 前端工程化
    • 代码规范
      • JavaScript 代码规范
      • CSS 代码规范
      • Vue 代码规范
      • Git Commit 规范
      • 代码规范配置
    • 网络安全与防御
    • 性能优化
    • 算法编程
    • 数据可视化
  • 🧑‍💻 面试相关
    • 面试知识总结
    • 面试问题总结
    • 面试常见编程
    • 面试资源汇总
  • 🍭其他
    • 项目经验❗️
    • 踩坑指南❗️
      • JavaScript 踩坑指南
      • CSS 踩坑指南
      • Vue 踩坑指南
    • 学习资源
    • 综合收藏夹
由 GitBook 提供支持
在本页
  • 1. 方法调用
  • 2. new 实例调用
  • 3. call/bind/apply 绑定
  • 3.1 call()
  • 3.2 apply()
  • 3.3 bind()
  • 3.4 总结
  • 4. 箭头函数中的 this
  • 5. 总结

这有帮助吗?

  1. 前端基础
  2. JavaScript
  3. JS 专题

this 的指向

上一页对象赋值与拷贝下一页异步操作

最后更新于4年前

这有帮助吗?

不管是什么场合,this都有一个共同点:它总是返回一个对象。javascript 的 this 不是在函数定义的时候确定的,而是在调用的时候确定的,指向调用者。

const A = {
  name: '张三',
  describe: function () {
    return '姓名:'+ this.name;
  }
};

const name = '李四';
const f = A.describe;
f() // "姓名:李四" - 相当于 window 调用了

1. 方法调用

通过对象来调用其方法函数 对象.方法函数(...),函数中的 this 指向调用该方法的对象。

const obj = {
    // 第一种方式,定义对象的时候定义其方法
    test() {
        console.log(this === obj);
    }
};

// 第二种方式,对象定义好之后为其附加一个方法(函数表达式)
obj.test2 = function() {
    console.log(this === obj);
};

// 第三种方式和第二种方式原理相同,是对象定义好之后为其附加一个方法(函数定义)
function t() {
    console.log(this === obj);
}
obj.test3 = t;

// 这也是为对象附加一个方法函数,但是这个函数绑定了一个不是 obj 的其它对象
obj.test4 = (function() {
    console.log(this === obj);
}).bind({});

obj.test(); // true  
obj.test2(); // true   
obj.test3(); // true    
obj.test4(); // false -受 bind() 影响,test4 中的 this 指向不是 obj

2. new 实例调用

在 es5 中,用 new 调用一个构造函数会创建一个新对象,而其中的 this 就指向这个新对象。

var data = "Hi";    // 全局变量

function AClass(data) {
    this.data = data;
}

var a = new AClass("Hello World");
console.log(a.data);    // Hello World
console.log(data);      // Hi

var b = new AClass("Hello World");
console.log(a === b);   // false

但是构造函数如果有 return 语句,且 return 语句是个对象,则 new 出来的新对象是指 return 的这个对象,如果 return 的是非对象数据类型,则 this 依旧指向 new 的新对象。

// 1
function fn(){  
  this.user = '追梦子';  
  return {};  
}
var a = new fn;  
console.log(a.user); //undefined

// 2
function fn(){  
  this.user = '追梦子';  
  return function(){};
}
var a = new fn;  
console.log(a.user); //undefined

// 3
function fn(){  
  this.user = '追梦子';  
  return 1;
}
var a = new fn;  
console.log(a.user); //追梦子

3. call/bind/apply 绑定

3.1 call()

函数实例的 call 方法,可以指定函数内部 this 的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数。call 方法的参数,应该是一个对象。如果参数为空、null 和 undefined,则默认传入全局对象。

// func.call(thisValue, arg1, arg2, ...)
// 第一个参数就是this所要指向的那个对象
​
var n = 123;
var obj = { n: 456 };
​
function a() {
  console.log(this.n);
}
​
a.call() // 123
a.call(null) // 123
a.call(undefined) // 123
a.call(window) // 123
a.call(obj) // 456

3.2 apply()

apply 方法的作用与 call 方法类似,也是改变 this 指向,然后再调用该函数。唯一的区别就是,它接收一个数组作为函数执行时的参数。

// 1、找出数组最大元素
var a = [10, 2, 4, 15, 9];
Math.max.apply(null,a) // 15
​
// 2、将数组的空元素变为undefined,空与undefined的区别在于遍历时空会被跳过
Array.apply(null, ['a', ,'b']) // [ 'a', undefined, 'b' ]
​
// 3、转换类似数组的对象,比如arguments对象
Array.prototype.slice.apply({0: 1, length: 1}) // [1]
Array.prototype.slice.apply({0: 1}) // []
Array.prototype.slice.apply({0: 1, length: 2}) // [1, undefined]
Array.prototype.slice.apply({length: 1}) // [undefined]
​
// 4、绑定回调函数的对象
var o = new Object();
o.f = function () {
  console.log(this === o);
}
var f = function (){
  o.f.apply(o); // 或者 o.f.call(o);
};
$('#button').on('click', f);

3.3 bind()

bind方法用于将函数体内的 this绑定到某个对象,然后返回一个新函数。

var counter = {
  count: 0,
  inc: function () {
    this.count++;
  }
};
​
var func = counter.inc.bind(counter);
func();
counter.count // 1

3.4 总结

类型
调用方式
第一个参数
其余参数

bind

返回一个函数

this指向改变后的对象

直接传递

apply

函数直接调用

this指向改变后的对象

用数组包裹参数

call

函数直接调用

this指向改变后的对象

直接传递

如果第一个参数为null或undefined,this 的指向就是全局变量,在浏览器里就是window对象。

不管我们给函数 bind 几次,fn 中的 this 永远由第一次 bind 决定。

4. 箭头函数中的 this

箭头函数中使用的 this,其实是直接包含它的那个函数或函数表达式中的 this。函数体内的this对象,是定义时所在的对象,而不是使用时所在的对象。或者可以说 箭头函数没有 this。

const obj = {
    test() {
        const arrow = () => {
            // 这里的 this 是 test() 中的 this,
            // 由 test() 的调用方式决定
            console.log(this === obj);
        };
        arrow();
    },

    getArrow() {
        return () => {
            // 这里的 this 是 getArrow() 中的 this,
            // 由 getArrow() 的调用方式决定
            console.log(this === obj);
        };
    }
};

obj.test();     // true

const arrow = obj.getArrow();
arrow();        // true

5. 总结

this 代表函数调用相关联的对象,通常页称之为执行上下文。

  1. 作为函数直接调用,非严格模式下,this指向window,严格模式下,this指向undefined

  2. 作为某对象的方法调用,this通常指向调用的对象

  3. 使用apply、call、bind 可以绑定this的指向

  4. 在构造函数中,new 调用时指的是被构造的对象

  5. 箭头函数没有单独的this值,this在箭头函数创建时确定,它与声明所在的上下文相同

简单来说就是:

  • 普通函数的this ==> 谁调用就是谁(经常变:谁调用是谁)

  • 箭头函数的this ==> 在谁的环境下this就是谁(不变:当前作用域),例如常见document/window等

如果你对内容有任何疑问,欢迎提交 或

📖
❕issues
✉️ email