不论是学习或是开发时,我们容易被 this 的指向搞的头昏眼花,接下来会花两个篇幅介绍 this 指向。
也因为 this 容易把人搞乱这边先列出影响 this 指向的方法:
本章节会先介绍上面 简易呼叫、物件函式呼叫 ,addEventListener() 监听事件触发的函式这三个。
bind ﹑apply 、 call 绑定方法、严格模式 下篇则会说明这两组状况,剩余的 new 建构式 、箭头函式 则会到他们各自章节介绍。
先来看看指向全域的(window) 的 this 写法:
var name = 'Ryder'
function showName() {
console.log(this.name)
}
showName()
这边直接使用 showName()
这种直接呼叫函式的方法,这种直接呼叫函式的方法我们称做 简易呼叫 ,只要是由简易呼叫触发的函式,他当中的 this
一律指向 window
。
可以看到范例中确实会显示 Ryder
,其实范例中 this
指向的是 window
。
顺带一题我们常用的 forEach()
、 filter()
中的 callback function ,他也是属於 简易呼叫 ,例如:
var name = 'Ryder'
var array = [1,2,3]
array.forEach(function(){
console.log(this.name) // Ryder * 3
})
array.filter(function(){
console.log(this.name) // Ryder * 3
})
再来看看 this
指向物件的写法:
var name = 'Ryder';
var obj = {
name: 'Jack',
showName() {
console.log(this.name) // Jack
},
}
obj.showName()
这个范例中 this 指向的是 obj
这个物件本身,关於物件函式的 this
指向有一个小撇步, this 指向的位置就是,呼叫函式 xxx()
的上一层物件 ,如图:
在使用另一个多层物件来看看结果是否一致
var name = 'Ryder';
var obj1 = {
name: 'Jack',
obj2: {
name: 'Alice',
showName() {
console.log(this.name) //Alice
},
}
}
obj1.obj2.showName()
在根据小撇步 this
会是 showName()
的上一层物件,图片就会是
而答案也是正确的,范例中的 this
指向的会是 obj2
,因此这个范例显示 'Alice'
function eventFn(){
console.log(this) // DOM
}
const box = document.querySelector('.box')
box.addEventListener('click', eventFn)
当我们使用 addEventListener
配合 click
、mouseover
等等事件触发的函式,他里面的 this
会是指向触发事件的 DOM 本身,比如这个范例的点击 box 时, this
就会是 class="box"
的 DOM 元素:
但要注意的是,这个 DOM 指向是 addEventListener()
特有的, 我们如果改成早期的 onclick
写法,则又会发现 this 指向的是 window
(全域) 。
这个范例,完整程序码可以参考 codepen :https://codepen.io/rider159159/pen/JjJrgjK
看到这里你可能会想说 this
的指向好像并不困难,上述都是建立在程序码拆开来说的情况,接下来就以上面观念,举出一些容易让人觉的混乱例子,并且在一一说明。
范例一:
var name = 'Ryder'
var obj = {
name :'Jack',
showName() {
name = 'Alice'
console.log(this.name)
},
}
var a = obj.showName
a()
结果会是 Alice
这是因为 obj.showName
赋值给变数 a
时,并没有使用 ()
呼叫 ,因此是将 showName
这个函式的整个内容,赋值到 a
变数上,接者呼叫 a()
来执行原本是 showName
函式中的语法,因此这边 a()
是 简易呼叫,所以 this
会指向 window
。
但是一执行 a()
,函式中 name = 'Alice'
这段语法就会将全域 name
的值替换成 Alice
,可以在浏览器打上 name
来查看全域的 name
是否被替换。
范例二:
var name = 'Ryder'
var obj = {
name: 'Jack',
showName() {
name = 'Alice'
console.log(this.name)
},
}
var a = obj.showName()
a
这个结果就会是 Jack ,虽然有把 obj.showName()
赋值到变数 a ,但这边还是由 obj.showName()
来呼叫 showName()
函式,因此这个函式的状况仍然如下图,自然 this 的指向就会是 obj
范例三:
function eventFn(){
var name = 'Jack'
array.forEach(function(){
console.log(this.name)
})
}
var name = 'Ryder'
var array = [1,2,3]
var box = document.querySelector('.box')
box.addEventListener('click', eventFn)
点击 box 时会显示?
结果会是显示三次的 Ryder
,虽然 eventFn
是由事件触发,但 this
所在的 funciotn
是 forEach
的 callback function ,而 callback function 也是属於简易呼叫的一种,因此 this
指向的是 window ,所以显示全域的 Ryder
。
JavaScript 核心篇 (六角学院)
<<: ActionScript 语言和你 SAY HELLO!!
利用父类别的变数来存取子类别物件的成员 public class Test{ public stat...
昨天我们已经做出用CreateML训练的模型来判断情绪的app,今天就要来展示我们的成果,那这边设...
今天要来研究一些常见的事件,来看看有那些东西会被系统纪录下来,他们的意义又是什麽。 笔者查了查发现不...
前言 阵列是一种资料结构,里面装载的资料必须是同性质的,不能同时装载着字串又装载着整数,且建立後阵列...
今天进度 : 鸟哥的 Linux 私房菜 -- 区域网路的环境设定 测试开放外网的时候,使用 net...