前言:最近开始在学新框架了,只是说原生的 javascript 也同时在补足观念中,最近在複习 this 看当初的笔记,有一种 WTF ,我在写什么三小?只能当自己是白纸再看一遍了。 呜呜
辅助资源:
猜猜这个 "this" 到底是什么?
https://youtu.be/8uqUD2F_W74
先说重点:
this 是 javascript 的一个关键字this 是 function 执行时 自动生成的一个内部物件随着function 执行场合不同,this 所指向的值,也有所不同多数情况下,this 代表呼叫 function 的物件关键:this 决定在于函式如何被呼叫
console.log(this);
在全域执行环境呼叫this,此时它会指向全域物件,也就是window
// 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哦!