JavaScript中this究竟是个啥

js中的this是什么,相信有经验coder肯定都用过,但被问起来又似懂非懂的搞不清楚,实际上this在定义的时候还不能确定是什么,只有在调用之后才会被确定,可以说this指的就是他所属的对象,一般分几种情况

单独的情况

单独的情况下,this指的是全局对象,例如在浏览器窗口中:

this === window // true

函数中使用

在函数中的this,指的是调用函数的对象,看几个例子:

function func(){
  console.log(this === window); // true
}
func();

其中func()实际就是window.func(),所以调用函数的对象即是window,所以this指向为window。

简单改造一下:

var obj = {};
function func(){
  console.log(this === window); // false
  console.log(this === obj); // true
}
obj.func = func;
obj.func();

由于调用函数的对象变成了obj,所以this的指向也变成obj。

方法中使用

方法中的this指向为该方法的拥有者对象。看一个例子:

var person = {
  name: '名称',
  sayName: function(){
    console.log(this.name); 
  }
}
person.sayName(); // 名称

其实方法与函数也是一样的,this的指向都是调用方法的对象,比如说改造一下:

var person = {
  name: '名称',
  sayName: function(){
    console.log(this.name); 
  }
}
person.sayName(); // 名称

var sayFunc = person.sayName;
sayFunc();// undefined

console.log(sayFunc === person.sayName); // true

可以看到定义的sayFunc和person.sayName实际上是指向同一个内存地址,而sayFunc()即等同于window.sayFunc(),所以this指向为window,内部的this.name即表示window.name,所以输出结果不同。

事件处理程序中

在事件处理程序中,this的指向是接收事件的元素对象:

var button = document.createElement('button');
button.onclick = function(e){
  console.log(this === button); // true
}
//手动触发事件
button.click();

事件处理中this指向的问题我还真的掉到坑里过,例如如下代码(示意代码):

function Item() {
    this.name = '组件名称';
    this.button = document.createElement('button');
    this.button.name = '按钮名称';
    this.sayName = function(){
        console.log(this.name);
    }
    this.clickBtn = function(){
        this.button.click(); // 手动触发按钮点击
    }
    this.button.onclick = this.sayName;  
}
var item = new Item();
item.sayName(); // 组件名称
item.clickBtn(); // 按钮名称

可以看到,最终触发的实际都是同一个方法sayName,但通过事件调用到的this就与预期不一致,我们在方法中实际是想要获得name=‘组件名称’,而不是具体的按钮名称,在实际使用中也会碰到类似的坑需要注意。解决也很简单:

function Item() {
    this.name = '组件名称';
    this.button = document.createElement('button');
    this.sayName = function(){
        console.log(this.name);
    }
    this.clickBtn = function(){
        this.button.click(); // 手动触发按钮点击
    }
    this.button.onclick = this.sayName.bind(this);
}
var item = new Item();
item.sayName(); // 组件名称
item.clickBtn(); // 组件名称

通过bind(this)改变了函数内部作用域,后面会详细说一说。

严格模式

在严格模式下,如果单独使用this,那么this的指向是全局对象:

"use strict"
this === window // true

由于JavaScript的严格模式不允许默认绑定,所以在严格模式中函数中使用this时,this是undefined:

"use strict"
function func(){
  console.log(this === undefined); // true
}
func();

显式函数绑定

在JavaScript中,有三个方法是可以将另一个对象作为参数调用对象方法,就是可以改变this。他们是call()、apply()和bind()。

这三个方法都可以用来调用函数。call接收多个参数,其中第一个参数为context,后面参数为被调用函数的参数列表。

apply方法也是方法调用函数,只接受两个参数,第一个参数是context,第二个参数为参数列表数组。可以说call和apply方法功能相同,只不过传参数形式不同。

传统调用方法:

function func(){
  return this === window;
}
func(); // true

相当于:

func.call(window); // true

改变call的第一个参数即可改变方法内部this:

var a = new Object();
func.call(a); // false

bind使用方法与call相似,支持多个参数,第一个参数为context,其余为被调用函数的参数列表。

不同的是bind不会立即调用,而是返回一个函数提供后续调用,并且调用时函数内部的this即是bind的第一个参数context,看一个例子了解bind

function fn(a, b, c) {
    console.log(a, b, c);
}
var fn1 = fn.bind(null, 'Dot');

fn('A', 'B', 'C');            // A B C
fn1('A', 'B', 'C');           // Dot A B
fn1('B', 'C');                // Dot B C
fn.call(null, 'Dot');      // Dot undefined undefined
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值