关于javascript 令人又爱又恨的 this

前言:最近开始在学新框架了,只是说原生的 javascript 也同时在补足观念中,最近在複习 this 看当初的笔记,有一种 WTF ,我在写什么三小?只能当自己是白纸再看一遍了。 呜呜

辅助资源:
猜猜这个 "this" 到底是什么?
https://youtu.be/8uqUD2F_W74

先说重点:

this 是 javascript 的一个关键字this 是 function 执行时 自动生成的一个内部物件随着function 执行场合不同,this 所指向的值,也有所不同多数情况下,this 代表呼叫 function 的物件

关键:this 决定在于函式如何被呼叫

console.log(this);

在全域执行环境呼叫this,此时它会指向全域物件,也就是window

image

// Outer Environmentconsole.log(this);// function statementfunction FunctionStatement() {  console.log(this);}FunctionStatement();// function expressionconst FunctionExpression = function() {  console.log(this);}FunctionExpression();

这里的 this 都代表 不管是 function statement 去执行;或是 使用 function expression 执行 只要在全域定义、呼叫创造其执行环境,这时的this会指向全域物件。

var kara = " p助"function a(){this.kara = "兔兔"}a();console.log(kara)

console.log 答案是

兔兔 !

我在全域宣告一个变数kara,赋值"p助"。

呼叫函式a时,函式a的执行环境被创造出来,同时函式a的执行环境也创造了它自己的this。

赋值兔兔"给函式a的this.kara,因为函式a自己的this指向全域,这下可好了,在全域的变数kara,其值被盖过从"p助"变成了"兔兔"。

所以回到这一题,这里的 this 就是 指全域

var name = '全域';function callMethod () {  var name = '区域'  console.log(this.name)}callMethod();

所以使用this必须要小心,得清楚它指向的物件对象是谁,否则可能会产生一些开发上的bug。

this 代表 function 执行时所属物件,而不是function 本身。

var Qoo = function (){ console.log(this.a);}var fpp = function (){   let a =123;   this Qoo();}fpp();

答案是 undefined

因为fpp() 透过 this Qoo 取得 Qoo() 这里的this Qoo指得是 指向 window.Qoo 。 而Qoo()的 this.a 并非fpp()中的123,而是指向 window.a 所以得到undefined 结果。

请看以下问题:

var name = '全域';function callMethod() {  var name = '区域'  console.log(this.name)  return function () {       // << 闭包    var name = '区域的内层变数';    console.log(this.name)  }}callMethod()();

1.这里的callMethod()() 执行的 第五行 function

那如果执行出来的结果会是什么?

答案是: console.log 出现两个全域

崩溃了吗?还没结束喔? 冷静三秒,数一下 质数

当没有特别指名this 的情况下, 预设的this 就是全域物件

物件下的不同函式呼叫方式,分别有三种呼叫方式

1.一般 function

var name = '全域';var object = {  name: 'Object 区域',  callMethod: function () {    var name = '区域';    console.log(this.name);  },}object.callMethod();

其中 callMethod 是一个 匿名函式(anonymous function),程式内容很简单,就是呼叫出 this 而已。最后则是使用 object.callMethod() 的方式来执行该方法。

Ans "Object 区域"

当某个函式是放在某一个物件里面时,那么该函式里面的 this 指称的就是该物件本身。

2.函式物件缩写 function

这是ES6的东西 可以补充

function 这个词彙如果使用在物件内,也可以省略 :function,省略后的语意是没有变化的,并没有转而使用箭头函式。

const newTeam = {  // ...  showPosture: function () {    console.log('我们是 红黄绿')  }}const newTeam = {  // ...  showPosture () {    console.log('我们是 红黄绿')  }}

两个代表一样意思。

var name = '全域';var object = {  name: 'Object 区域1',  callMethod: function () {    var name = '区域';    console.log(this.name);  },  abbCallMethod () {    var name = '缩写函式区域';    console.log(this.name);  }}object.callMethod();   // object.abbCallMethod();

第二个 abbCallMethod 就是物件函式缩写,
所以跟第一个答案 callMethod() 所得到的答案是一样的。

3.箭头函式

var name = '全域';var object = {  name: 'Object 区域',   arrowCallMethod: () => {    var name = '箭头函式区域';    console.log(this.name);  } }object.arrowCallMethod();

这里要特别注意,箭头函式 答案是 全域

因为 箭头函式 特性有强制绑定 this,所以当我们在写函式时要注意 。

DOM 物件调用

var elements = document.getElementsByTagName('div');function style () {  console.log(this);  this.style.border = '1px solid red';}for (var i = 0; i < elements.length; i++) {  elements[i].addEventListener('click', style, false);}

这里 的this 就是我们所执行的 dom 事件 的地方,点击到的地方

函式建构式 this

var name = '全域';var callMethod = function (newName) {  this.name = '权权权';  console.log(this.name);}var myName = new callMethod();console.log(myName.name);

console.log 出来的答案是 权权权

因为 myName 继承了 callMethod 方法 ,所以 myName.name
答案是 权权权

var name = '全域';var callMethod = function (newName) {  this.name = newName || '区域';}var myName = new callMethod('权权权');console.log(this.name);console.log(myName.name);

这里的 this name  还是指向 全域。
myName.name 就是函式建构式 指的是 权权权。

接下来看陷阱题

 var name = '全域';var callMethod = (newName) => {  this.name = newName || '区域';}var myName = new callMethod('卡斯伯');console.log(this.name);console.log(myName.name);

这里不管是哪一个 console.log 都无法执行,因为箭头函式不能当建构式。

bind, apply, call

基本上只要看到 bind, apply, call 里面的this  就是代表绑定的物件

call、apply、bind 三者都是 JavaScript Function 的内建函式,他们与 this 的关係重大,除此之外,call & apply 可以作为呼叫 Function 的另一个手段,而 bind 则会回传一个经过包裹后的 Function 回来。

function callMethod () {  var name = '区域'  console.log(this.name)}callMethod.call({name: '鲁鲁米'});

这里的 callMethod 所指就是 鲁鲁米

bind, call, apply 的差异

可以看这篇文章:
让你弄懂call、apply、bind的应用和区别
https://juejin.im/post/5a9640335188257a7924d5ef

影响 this 的几种情境

纯粹的调用window物件的方法调用ObjectDOM 物件调用Object建构式的调用Object > 属于 new 它的物件bind, apply, call传入的物件箭头函示 >箭头函数会自动将 this 变数绑定到其定义时所在的物件window 或 定义的环境

注意事项

先说结论:setTimeout中所执行函数中的this,永远指向window!!注意是要延迟执行的函数中的this哦!


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章