Day [4] — this:指定物件 — JS之浸猪笼系列
我们在前面几章知道 this 会依据呼叫方式印出不同结果,那如果我们希望可以存取 this 的某个特定内容呢?要指定 this 取得其内容有几种方法:
设定变数:重新指向 this
//来个範例!//记得用回推的方式看会比较清楚function callName() { console.log('区域', this.name); //这里会印出区域结果 var that = this; //让that变数 = this 在被呼叫时间点的值 setTimeout(function () { console.log('全域', this.name); //上一章我们提过,这里会从全域(Window)去寻找 console.log('区域', that.name); // 因为我们已经指定 that,所以只会去寻找被呼叫时间点的值 }, 10);}var name = '全域阿婆';//全域(Window)var auntie = { //区域(这里的 function 指向全域的 function,但不重要) name: '漂亮阿姨', callName: callName }auntie.callName();//我们呼叫 auntie 里的 callName,//callName = function callName,所以他将会印出以下三行的结果://console.log('区域', this.name);//console.log('全域', this.name); //console.log('区域', that.name); //////////////解析一下**//第一个:console.log('区域', this.name);//印出: 区域 漂亮阿姨**//我们将这里的 this.name 回推,往外看 第一个先看到 function callName//function callName 是 var auntie 里的物件 callName: callName//所以这里的 this是指向 auntie ,而 auntie里的name是 漂亮阿姨//故就会印出 区域 漂亮阿姨**//第二个:console.log('全域', this.name);//印出: 全域 全域阿婆**//一样我们将这里的 this.name 回推, setTimeout(function () //是切分变数的最小範围(也就是scope),故this 往外推的时候指向全域(window)//所以他会找到的是 var name = '全域阿婆';//故印出 全域 全域阿婆//**第三个:console.log('区域',** that.name**);//印出: 区域 漂亮阿姨**//我们在 function callName() 中指定 var that = this;//记得我们是以 auntie.callName();的方式呼叫的//所以结果就会跟 第一个 一样
设一个 变数 = this
如果你看懂上面了,应该会想说 that 一定要写 that 吗?
其实并不用,这里的变数名称可以自己指定,例如一般常用的 a 或其他自订名称都可以。
var that = this ;//that可以替换成任意的自订名称
除了设定变数以外还有其他方式可以指定 this 吗?
有三个方式可以使用,分别是 bind() / call() / apply()
.bind()
产生副本,藉由副本读取资料
//来个範例吧!var obj = {x : 123,}//obj物件中,x的值是123var func = function(){console.log(this.x);}func(); //这里我们严格指定 var func = function(),故 undefiendfunc.bind(obj); //当我们使用 .bind(obj),会替我们将 this 指向 obj ,故得123
.call()
.call() 调用的函式可以直接传入新的物件,使其作为 this 所指向的物件。
//来个範例吧!var name = '全域阿婆';function callName() { console.log(this.name);}callName(); // 去寻找了全域,故印出'全域阿婆'callName.call({name: '漂亮阿姨'}); // 这边直接将this指向'漂亮阿姨','漂亮阿姨'作为物件被传入 callName 中
.apply()
.apply() 调用的函式可以直接传入新的物件,使其作为 this 所指向的物件。
var name = '全域阿婆';function callName() { console.log(this.name);}callName(); // 去寻找了全域,故印出'全域阿婆'callName.apply({name: '漂亮阿姨'}); // 这边直接将this指向'漂亮阿姨','漂亮阿姨'作为物件被传入 callName 中
....等等,先听我解释!(鼻要打脸)
.call() 和 .apply() 的区别
//来个範例吧!function add(c, d) { return this.a + this.b + c + d;}var o = {a: 1, b: 3};add.call(o, 5, 7); // 16// 第一个参数(parameter)是调用了 this 的物件,// 后续参数(parameters)会作为函式呼叫内的参数(arguments)而通过add.apply(o, [10, 20]); // 34// 第一个参数(parameter)是调用了 this 的物件,// 第二个参数的阵列作为函式呼叫内的参数(arguments)之构件
.call() 和 .apply() 的区别就在于传入的方式,.call()传入参数的方式是以 『 , 』隔开,而 .apply() 则是传入整个阵列作为参数。
bind / call / apply
bind(綑绑)
产生副本,藉由副本读取资料。
bind 会在呼叫前就先绑定某个物件(类似产生副本),让他不管怎么呼叫都有固定的 this。
call (呼叫)/ apply(应用)
使用在 context 时常变动的场景(例如上面的範例 o 就是 context ),依照呼叫时需要带入不同物件作为该 function 的 this ,在呼叫下就立即执行。
引用及参考资讯
铁人赛:JavaScript 的 this 到底是谁?
MDN : this
浅谈 JavaScript 头号难题 this:绝对不完整,但保证好懂
What's THIS in JavaScript ? [上]