大雪纷飞,永真在井上面丢垃圾一封信,信上写着如下内容:
谁最终调用,
this
就指向谁。
那么如何理解永真写的话呢?请接着往下看~
我(this)的职责就是保护
指向少主,少主喜欢用window玩游戏,姑且叫少主window吧。
this
指针(window
(console.log(this); // window
a
函数,写全局函数的话,也是指向的 window
function a() {
console.log(this);
}
a() // window
//实际上是 window.a(); 我们可以展开window看看
window
(this
也会指向window
。// setInterval 也是 window 下的方法
setInterval(function () {
console.log(this); // window
}, 1000)
为了追寻长生不老,山上的僧人开始作妖,严格实验了好多小孩,最后就一个小女孩活了下来,成了变若之子(假的皇子)
this
指向 undefined
undefined
了)function a() {
"use strict";
console.log(this);
}
a() // undefined
console.log(this);
补充:什么是严格模式
简单来说就是为了更好的规范 JavaScript 语言的书写,具体请参考阮一峰的严格模式详解。
情景:我们带着皇子一路小跑,走出隧道,只见弦一郎在堵门,
(简介,游戏名《只狼》,第一个BOSS的名字)
开门见山!!先来打苇名弦一郎。
var name = '我是全局name'
function fn() {
var name = '我是fn';
console.log(this.name);
}
var objA = {
name:'我是objA',
showA:fn
}
var objB = {
name:"我是B对象",
showB:objA
}
objB.showB.showA()
请问最终打印的是什么呢?这里我先不告诉你们答案,先跟着我一步一步往下走~
分支1:没打过弦一郎(
没做对):失去手臂,等待佛雕师(作者)给你安义肢(讲解)。
分支2:打过弦一郎:同样失去手臂(不要怪我卑鄙!我叫屑一狼),等待佛雕师…
战果:经验 +0,金币 -0,金钱 -0,HP -0,失去真手臂
次日:看到淡淡的油灯光亮,发现自己躺在破旧寺庙的草席上,并且获得了义肢。
战果:获得义肢,HP +100
来看一下栗子(苇名城杂兵,经验怪 ):
function fn() {
console.log(this);
}
var obj = {
show: fn
};
obj.show(); // {show: ƒ}
// this 指向的关键在于是谁最终执行的
成功忍杀
看懂了这个:金钱+5,经验+5
第二个栗子(苇名城杂兵,经验怪 ):
function fn() {
console.log(this);
}
var obj = {
show: fn() // 因为fn才最终执行者,括号代表执行!而 fn 是 window 下的函数
};
obj.show; // window
成功忍杀:HP+5,金钱+5,经验+5
获得少主给的:伤葫芦,楔丸
此时来到了苇名城 城邑外围 城门道,遇到了第一个boss(河源田直盛)
function fn() {
console.log(this.name);
}
var objA = {
name:'我是A对象',
showA:fn
}
var objB = {
name:"我是B对象",
showB:objA
}
objB.showB.showA() // 我是A对象
// 为啥指的是objA呢?
// 你要清除是谁最终调用的fn,是不是objA里才有fn啊,最终调用的也是objA!所以指向就是objA。
成功忍杀
看懂了这个:HP+10,金钱+10,经验+10
获得技能:识破
总结:以上例子可以说明,this的指向跟函数写在哪里没啥关系,关键在于最终调用者是谁!
情景:来到了被锁住的赤鬼。发现兜里没有月隐糖,也没有喷火器,没关系,有闪避+突刺,超级逃课打法。
var name = '我是全局name';
var obj = {
name:'我是obj的name',
fn:function () {
console.log(this.name);
}
}
var xxx = obj.fn;
xxx(); // 我是全局name
// 这里为什么是全局name呢
// 因为xxx是最终调用者,而xxx属于window,所以this指向的是window
成功忍杀:获得佛珠,忍者之药理知识•甲
失败:死,(少主的龙血之力,无尽复活)
接着来到下一关
情景:来到了苇名城 正门外城区,遇到鬼庭形部雅孝,不慌,追的驴的尾巴,砍就完事儿了,
逃课
var name = '我是全局name';
var obj = {
name:'我是obj的name',
fn:function () {
console.log(this.name);
}
}
function xxx(param) {
// 2. 然后在这里执行函数
param();
// 相当于 window.param()
}
// 1. 此时我把函数体当成参数传递进去了
xxx(obj.fn) // 我是全局name
成功忍杀:战斗记忆:鬼庭形部雅孝(攻击力强化),机关筒(义手强化工具)。
失败:死,(少主的龙血之力,无尽复活)
接着到了火牛关
情景:火牛血厚,建议买鞭炮(
前面的都看懂了)
var name = '我是全局name';
var obj = {
name:'我是obj的name',
fn:function () {
console.log(this.name);
}
};
var obj1 = {
name:"福山润"
};
obj1.xxx = obj.fn;
obj1.xxx(); // 福山润
成功忍杀:佛珠,忍者药理·乙。
失败:死,减一半的¥
我们可以通过call
(干柿子 )、apply
(米 )和bind
(樱龙之泪 )方法更改指针的指向(不同结局)。
// 显示转换
var objA = {
name: "aaa"
};
var objB = {
name: "bbb"
};
var objC = {
name: "ccc"
};
var name = '我是全局name';
function fn() {
console.log(this.name);
}
fn(); // 我是全局name
fn.call(objA); // aaa
fn.apply(objB); // bbb
fn.bind(objC)(); // ccc
成功忍杀枭,樱龙,白蛇:获得樱树枝,樱龙之泪,鲜柿子,月隐糖
失败:死,(少主的龙血之力,无尽复活),金钱 -1/2
某些方法也可以显式的更改指针,比方说forEach
var obj = {
name:'铃木雅之'
};
var arr = [1,2,3,4];
arr.forEach(function () {
console.log(this.name); // 4 * 铃木雅之
},obj)
越到后期,游戏所需要的技巧就越高,熟练度也就越重要,(不我就是平a格挡流 )
显式绑定的优先级 大于 隐式绑定的优先级,显式>隐式>默认
var objA = {
name:'aaa',
fn:function () {
console.log(this.name);
}
}
var objB = {
name:'bbb'
}
// 前面的是objA.fn() ,隐式绑定,省略了括号,
// 后面的call()是显示绑定
// 当显式隐式都存在的时候,显式优先级更大
objA.fn.call(objB) //bbb
发现个小胖子,他跟同伴走丢了,他想要我给他找彩色风车…
其实这个跟之前讲的蛮像的,我就在这里再重复一下叭
<body>
<div class="btn">点我div>
body>
<script>
function show(){
console.log(this);
}
document.querySelector('div').addEventListener('click', show);
// 点我
document.querySelector('div').addEventListener('click', show());
// window
script>
成功忍杀:卧槽小胖子好可怜的,
别杀了,骗到商人那里打扫战场
失败:良心受到谴责嗯~ o( ̄▽ ̄)o
来到了苇名之底 毒沼,狮子猿 new 出一个小狮子猿,二打一,太难了
function Person() {
// 1. 刚开始这里的this指向的是 window
// 因为这是函数啊
this.name = '堺雅人'
}
// 2. 然后通过new方法改变了 this 指向
var p = new Person();
console.log(p.name);
成功忍杀:战斗记忆:无首狮子猿,佛珠*2,血刀术(使用不死斩断绝不死后获得)
失败:死,减一半的¥
来到了苇名城 城邑外围 城门道,看到个没有头的家伙,无首,尼玛打了一架,被戳了菊花,屏幕上出现了:菜
取决于:外层(上层)作用域中的this
,和他本身没有关系
var name = 'www';
function fn() {
// 这里就是箭头函数上层作用域
// 这里的 this 指向 window
console.log(this.name);
return () => {
console.log(this.name);
}
}
var objA = {
name:'aaa'
};
var xxx = fn(); // www
xxx(); // www
成功忍杀:哼将之降灵
失败:死,减一半的¥
var name = 'www';
function fn() {
// 这里就是箭头函数上层作用域
// 这里的 this 通过 call 方法指向了 objA
console.log(this.name);
return () => {
console.log(this.name);
}
}
var objA = {
name:'aaa'
};
var xxx = fn.call(objA); // aaa
xxx(); // aaa
情景:最后来到了苇名城主城 贮水城区,弦一郎喝了变若(
弱) 水,剑圣苇名一心想要实现他儿子的最后的愿望,就是守护这片土地,于是重返战场…
this
它既是吃软饭的,也很专一var name = 'www';
function fn() {
// 吃软饭的箭头函数this:一直跟随着上层作用域
// 这里就是箭头函数上层作用域
console.log(this.name);
return () => {
console.log(this.name);
}
}
var objA = {
name:'aaa'
};
var objB = {
name:'bbb'
};
// 此时xxx就是箭头函数
var xxx = fn.call(objA); // aaa
// 我这时修改箭头函数的指向,然并卵
// 箭头函数中的this很专一,取决于外层作用域的指向
xxx.call(objB); // aaa
this
,那么只能修改上层作用域的this
,比方说上面的例子// 只有修改上层作用域的this,才能改变箭头函数的this
var xxx = fn.call(objb); // bbb
// 即使是修改了箭头函数的指向也没用
xxx.call(objA); // bbb
成功忍杀:战斗记忆:剑圣 苇名一心,秘传·龙闪(技能)。
失败:死,我死了200多回hhhh。
通关,赶快去救小皇子~
执行上下文是指 函数调用时 在执行栈中产生的变量对象,这个变量对象我们无法直接访问,但是可以访问其中的变量、this
对象等。
let fn, bar; // 1、进入全局上下文环境
bar = function(x) {
let b = 5;
fn(x + b); // 3、进入fn函数上下文环境
};
fn = function(y) {
let c = 5;
console.log(y + c); //4、fn出栈,bar出栈
};
bar(10); // 2、进入bar函数上下文环境
每次函数调用时,执行栈栈顶都会产生一个新的执行上下文环境,JavaScript引擎会以栈的方式来处理它们,这个栈,我们称其为函数调用栈(call stack)。栈底永远都是全局上下文,而栈顶就是当前处于活动状态的正在执行的上下文,也称为活动对象(running execution context,图中蓝色的块),区别与底下被挂起的变量对象(执行上下文)。
用于表达源代码中一个固定值的表示法