JS—this指向问题全面解析(十)

一.前言

this关键字是javascript中最复杂的机制之一,是一个被自动定义在所有函数作用域中的一个很特别的关键字。

1.1为什么要用this关键字?(我们先看下面两端代码)

1.1为什么要用this关键字?(我们先看下面两段代码)

 function identify() {
   
      return this.name.toUpperCase();
    }
    function speak() {
   
      var greeting = "HELLO" + identify.call(this);
      console.log("greeting");
    }
    var me = {
   
      name: "Kyle",
    };
    var you = {
   
      name: "Reader",
    };
    identify.call(me);
    identify.call(you);
    speak.call(me);
    speak.call(you);
//该例子只是简单的举例,重在说明this的用处

可以看见这段代码可以在不同的上下文对象(me,you)重复使用函数identify()和speak(),不用针对每个对象编写不同版本的函数

可是,假如我们不使用this,则需要给identify和speak显示传入一个上下文对象(参数)

function identify(context) {
   
    return context.name.toUpperCase();
}
function speak(context) {
   
    var greeting = "HELLO" + identify.call(this);
    console.log("greeting");
}

identify(you);
speak(me);

这样子当然可以实现功能,但随着使用模式越来越复杂,代码会变得更加混乱,而this更加简介且易于复用。

1.2.1对this的误解

在彻底认识this之前,我们需要消除一些对this的误解。

误解一:this指向函数自身

问:为什么需要从函数内部引用函数自身呢?

经典案例:

  • 递归(比如写一个树形组件的时候)
let data = {
   
    name: '1',
    children: [
        {
   
            name: '1',
            children: [
                {
   
                    name: '1.1.1'
                }
            ]
        },
        {
   
            name: '1.2',
            children: []
        },
        {
   
            name: '1.3',
            children: []
        }
    ]
}

function renderTreeChildren(node) {
   
    console.log(node.name, node.children);
    if (node.children && node.children.lenth) {
   
        node.children.map(item => renderTreeChildren(item))
    }
}
renderTreeChildren(data)

// 1 [
//     { name: '1', children: [ [Object] ] },
//     { name: '1.2', children: [] },
//     { name: '1.3', children: [] }
//   ]
  • 在写第一次被调用后自己解除绑定的事件处理器的时候
let btn = document.getElementById("btn")

btn.onClick=function(){
   
//.....
btn.onClick=null;
}

以上两个案例都需要用this来指向函数本身。(虽然案例没体现出来),但实际上,这就会给人造成误解,认为this确实是指向函数本身。这是一个误解!
下面这个例子证明this不指向函数本身,需求是记录foo被调用的次数

function foo(num) {
   
    console.log('foo' + num);
    //记录foo被调用的次数
    this.count++;
}
foo.count = 0
let i
for (let i = 0; i < 10; i++) {
   
    if (i > 5) {
   
        foo(i)
    }
}
// foo6
// foo7
// foo8
// foo9
// 
// 有四次输出,证明被调用了四次
console.log(foo.count);//0
console.dir(foo);
/**
 * console.log()方法可以打印输出结果
而console.dir()方法可以在控制台显示指定javascript对象的属性。打印出该对象的所有属性和属性值.
 */

可以看见,我们在foo函数内部添加了count属性,也通过参数传递证明了函数确确实实被调用了四次,也就是说this.count的值应该是4,但在最后打印foo.count的时候,发现值为0,这说明在函数内部,this.count并不等于foo.count。所以this并未指向foo函数本身。

结论:this并不指向函数本身

1.2.2那么,如果我们确实需要在函数内部引用函数本身,该怎么做?

案例一:有的人会绕过理解this的真正意义和工作原理,通过词法作用域来解决,如下

function foo(num) {
   
    console.log('foo' + num);
    //记录foo被调用的次数
    data.count++;
}
let data = {
   
    count: 0
}
let i
for (let i = 0; i < 10; i++) {
   
    if (i > 5) {
   
        foo
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三千洲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值