问道this

2024-02-05 23:50
文章标签 问道

本文主要是介绍问道this,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

this 指向详细解析(箭头函数)

前言

this 指向问题是入坑前端必须了解知识点,现在迎来了ES6时代,因为箭头函数的出现,所以感觉有必要对 this 问题梳理一下,遂有此文

在非箭头函数下, this 指向调用其所在函数的对象,而且是离谁近就是指向谁(此对于常规对象,原型链, getter & setter等都适用);构造函数下,this与被创建的新对象绑定;DOM事件,this指向触发事件的元素;内联事件分两种情况,bind绑定, call & apply 方法等, 容以下一步一步讨论。箭头函数也会穿插其中进行讨论。

全局环境下

在全局环境下,this 始终指向全局对象(window), 无论是否严格模式;

console.log(this.document === document); // true// 在浏览器中,全局对象为 window 对象:
console.log(this === window); // truethis.a = 37;
console.log(window.a); // 37

函数上下文调用

函数直接调用

普通函数内部的this分两种情况,严格模式和非严格模式。

非严格模式下,this 的值默认为全局对象window

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

严格模式, this的值为undefined

function f2(){"use strict"; // 这里是严格模式return this;
}f2() === undefined; // true

对象中的this

对象内部方法的this指向调用这些方法的对象,

  1. 函数的定义位置不影响其this指向,this指向只和调用函数的对象有关。
  2. 多层嵌套的对象,内部方法的this指向离被调用函数最近的对象(window也是对象,其内部对象调用方法的this指向内部对象, 而非window)。
//1
var o = {prop: 37,f: function() {return this.prop;}
};
console.log(o.f());  //37
var a = o.f;
console.log(a()):  //undefinedvar o = {prop: 37};function independent() {return this.prop;
}o.f = independent;console.log(o.f()); // logs 37//2
o.b = {g: independent,prop: 42
};
console.log(o.b.g()); // logs 42
原型链中this

原型链中的方法的this仍然指向调用它的对象,与以上讨论一致;看个例子,

var o = {f : function(){ return this.a + this.b; }
};
var p = Object.create(o);
p.a = 1;
p.b = 4;console.log(p.f()); // 5

可以看出, 在p中没有属性f,当执行p.f()时,会查找p的原型链,找到 f 函数并执行,但这与函数内部this指向对象 p 没有任何关系,只需记住谁调用指向谁。

以上对于函数作为getter & setter 调用时同样适用。

构造函数中this

构造函数中的this与被创建的新对象绑定。

注意:当构造器返回的默认值是一个this引用的对象时,可以手动设置返回其他的对象,如果返回值不是一个对象,返回this。

function C(){this.a = 37;
}var o = new C();
console.log(o.a); // logs 37function C2(){this.a = 37;return {a:38};
}var b = new C2();
console.log(b.a); // logs 38

以上两个例子内部的this都指向对象o, 看到这里的你不妨在控制台执行下以上代码,看看对象 o 和 b ,这些是属于构造函数的内容了,此处不多做介绍。(C2函数中的this.a = 37 对整个过程完全没有影响的, 可以被忽略的)。

call & apply

当函数通过Function对象的原型中继承的方法 call() 和 apply() 方法调用时, 其函数内部的this值可绑定到 call() & apply() 方法指定的第一个对象上, 如果第一个参数不是对象,JavaScript内部会尝试将其转换成对象然后指向它。

例子:

function add(c, d){return this.a + this.b + c + d;
}var o = {a:1, b:3};add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34function tt() {console.log(this);
}
// 返回对象见下图(图1)
tt.call(5);  // Number {[[PrimitiveValue]]: 5} 
tt.call('asd'); // String {0: "a", 1: "s", 2: "d", length: 3, [[PrimitiveValue]]: "asd"}

bind 方法

bind方法在ES5引入, 在Function的原型链上, Function.prototype.bind。通过bind方法绑定后, 函数将被永远绑定在其第一个参数对象上, 而无论其在什么情况下被调用。

function f(){return this.a;
}var g = f.bind({a:"azerty"});
console.log(g()); // azertyvar o = {a:37, f:f, g:g};
console.log(o.f(), o.g()); // 37, azerty

DOM 事件处理函数中的 this & 内联事件中的 this

DOM事件处理函数

  1. 当函数被当做监听事件处理函数时, 其 this 指向触发该事件的元素 (针对于addEventListener事件)
  // 被调用时,将关联的元素变成蓝色function bluify(e){//在控制台打印出所点击元素console.log(this);//阻止时间冒泡e.stopPropagation();//阻止元素的默认事件e.preventDefault();      this.style.backgroundColor = '#A5D9F3';}// 获取文档中的所有元素的列表var elements = document.getElementsByTagName('*');// 将bluify作为元素的点击监听函数,当元素被点击时,就会变成蓝色for(var i=0 ; i<elements.length ; i++){elements[i].addEventListener('click', bluify, false);}

以上代码建议在网页中执行以下,看下效果。

内联事件
内联事件中的this指向分两种情况:

  1. 当代码被内联处理函数调用时,它的this指向监听器所在的DOM元素
  2. 当代码被包括在函数内部执行时,其this指向等同于 函数直接调用的情况,即在非严格模式指向全局对象window, 在严格模式指向undefined

页面的代码块


在浏览器内显示三个按钮


依次点击上边的三个按钮后在控制台的输出结果,

建议自己操作一遍以便于更好的理解。

setTimeout & setInterval

对于延时函数内部的回调函数的this指向全局对象window(当然我们可以通过bind方法改变其内部函数的this指向)
看下边代码及截图

//默认情况下代码
function Person() {  this.age = 0;  setTimeout(function() {console.log(this);}, 3000);
}
var p = new Person();//3秒后返回 window 对象--------------------------------------------------------------------
//通过bind绑定
function Person() {  this.age = 0;  setTimeout((function() {console.log(this);}).bind(this), 3000);
}var p = new Person();//3秒后返回构造函数新生成的对象 Person{...}


箭头函数中的 this

由于箭头函数不绑定this, 它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值,

  1. 所以 call() / apply() / bind() 方法对于箭头函数来说只是传入参数,对它的 this 毫无影响。
  2. 考虑到 this 是词法层面上的,严格模式中与 this 相关的规则都将被忽略。(可以忽略是否在严格模式下的影响)

因为箭头函数可以捕获其所在上下文的this值 所以

function Person() {  this.age = 0;  setInterval(() => {// 回调里面的 `this` 变量就指向了期望的那个对象了this.age++;}, 3000);
}var p = new Person();

以上代码可以得到我们所以希望的值,下图可以看到,在setTimeout中的this指向了构造函数新生成的对象,而普通函数指向了全局window对象


var adder = {base : 1,add : function(a) {var f = v => v + this.base;return f(a);},addThruCall: function inFun(a) {var f = v => v + this.base;var b = {base : 2};return f.call(b, a);}
};console.log(adder.add(1));         // 输出 2
console.log(adder.addThruCall(1)); // 仍然输出 2(而不是3,其内部的this并没有因为call() 而改变,其this值仍然为函数inFun的this值,指向对象adder

bind() & apply() 读者可以自行测试

对于是否严格模式示例代码(可以复制进控制台进行验证)

var f = () => {'use strict'; return this};
var p = () => { return this};
console.log(1,f() === window);
console.log(2,f() === p());
//1 true
//2 true

以上的箭头函数都是在方法内部,总之都是以非方法的方式使用,如果将箭头函数当做一个方法使用会怎样呢?
上例子

var obj = {i: 10,b: () => console.log(this.i, this),c: function() {console.log( this.i, this)}
}
obj.b();  // undefined window{...}
obj.c();  // 10 Object {...}

可以看到,作为方法的箭头函数this指向全局window对象,而普通函数则指向调用它的对象

这篇关于问道this的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/682547

相关文章

问道管理:如何学习炒股?

炒股是一种高危险高回报的出资方式。比较于传统的储蓄方式,炒股能够获得更高的收益,但也需求更多的知识和技巧。那么,如果想要学习炒股,应该从何处入手呢?   一、基础知识 首先,咱们需求了解股票市场的根本知识。包括股票的界说、股票的交易机制以及股票市场的根本运作规矩等。这些基础知识能够协助咱们更好地理解炒股的实质,也能够让咱们更好地选择股票和拟定买入、卖出战略。 二、出资理念 其次,咱们还需

问道管理:股票交易手续费?

股票生意过程是中需求支付的手续费用。其价格一般由证券公司或生意所拟定,是股票生意过程中必需求支付的费用之一。股票生意手续费的凹凸关系着出资者的出资本钱,而影响生意手续费的要素则包括证券公司种类、超时生意、生意价格、股票生意数量等多方面要素。 从证券公司视点分析,生意手续费是证券公司的首要盈余来源,而生意手续费的凹凸则影响着证券公司的商场占有率。现在商场上的证券公司绝大多数挑选在手续费上进行竞争,

《王石哈佛问道》--王石

这边书《王石哈佛问道》,作者是万科公司的董事长王石。 说说我看这本书的感受,60岁的人还冲满这这样的奋斗精神(干劲),实在是令我很佩服。作为我一个快要25岁的年轻人来说,我还有什么理由 每天对社会充满抱怨,充满仇恨;我应该放宽些,我还年轻,更应该去折腾.... By the way,Reading this book is good for you and you can get some t

php面试可能会被问道的技术题汇总

1.nginx 连接多台php的方式 2.线程和进程的区别 3.用到过的传输协议 4.yii2和yii不一样的三个点 5.实现autoload 6.yii2 的路由 7.nginx如何调用php 8.php-fpm的作用和工作原理 9.memcache和redis的区别 10.web 安全 11.nginx的负载均衡如何配置 12.如何查询myqsl的从库状态 13 了解哪

问道管理:分时高抛低吸策略?

分时高抛低吸是股市中的一种买卖战略,也是投资者经常运用的一种方法。这种战略经过剖析图表、股价和时刻,尽可能减少危险,添加收益。下面从多个视点对十二种分时高抛低吸进行剖析。 视点一:什么是分时高抛低吸? 分时高抛低吸是指在短时刻内经过高卖低买的方法取得收益。这种战略需求根据对商场的判别,以及对股票走势的剖析来决议股票买卖的时机。在必定程度上,这种战略能够较好地规避股市的动摇危险。 视点二:

问道管理:股票打板风险大吗?怎么降低打板风险?

在股票市场上,一些出资者喜爱低吸,一些喜爱打板,那么,股票打板危险大吗?怎么下降打板危险?下面问道管理为大家准备了相关内容,以供参阅。   股票打板通常是指在个股涨停时买入,这种买入方法,与其他的买入方法相比较,其危险性要高一些,出资者能够经过以下方法来下降打板危险: 1、在打板过程中出资者应该挑选成交量较大,特别是在涨停处存在较大的封单,换手率不是很高的个股,这说明个股当天买入量较多,出资