this 是 js 中的关键字,看起来很混乱,但其实很好理解,用网上通用的一句话来讲就是: this 的指向在函数定义时肯定不了,只有函数指向的时候才能肯定 this 到底指向谁,也便是说this的卒中指向的是那个调用他的对象javascript
总结起来就六个字 谁调用,指向谁
java
例子1数组
function foo() {
var name = "我爱js";
console.log("this", this); // this window
console.log("name", this.name)// this undefined
}
foo()
复制代码
为何这里的 this 是window对象,由于咱们是在全局做用域中调用的,其实是省略了 window. 看以下代码的调用方式,跟上一个彻底相同bash
例子2app
function foo() {
var name = "我爱js";
console.log("this", this); // this window
console.log("name", this.name)// this undefined
}
window.foo()
复制代码
效果跟上面是彻底相同的函数
例子3ui
var foo = {
name: "JavaScript",
child: function () {
console.log("this", this) // this {name: "JavaScript", child: ƒ}
console.log("name", this.name) //name JavaScript
}
}
foo.child()
复制代码
在这里调用者是 foo, 因此this指向的是 foo 然而事实是这样吗,再看看上面的例子this
例子4spa
var foo = {
name: "JavaScript",
child: function () {
console.log("this", this) // this {name: "JavaScript", child: ƒ}
console.log("name", this.name) //name JavaScript
}
}
window.foo.child()
复制代码
这里最终调用者是window,可是this并无指向window,这是怎么回事?难道是六字真言有问题?要弄懂这个问题,咱们须要再看几个例子prototype
例子5
var foo = {
a: 1,
b: {
a: 2,
fn: function() {
console.log(this.a) // 2
}
}
}
foo.b.fn()
复制代码
并且这个例子中的this也一样没指向foo, 看到这里,可能会有疑惑,会推翻六字箴言,可是,若是再补充几句话,就会消除歧义
非严格模式下,若是一个函数中有this,而且这个this没有被上一级调用,那么这个this的指向就是window,具体参考例子1,例子2
若是一个函数中有this,这个函数被上一级对象调用,那么this就指向上一级对象,具体参考例子3
若是一个函数有this,假如调用这个函数的有多级对象,那么this指向的是调用它的上一级对象,具体参考例子5
咱们再来验证一下状况3 例子 6
var foo = {
a: 1,
b: {
//a: 2,
fn: function() {
console.log(this.a) // undefined
}
}
}
foo.b.fn()
复制代码
此时,咱们看到,输入的值是undefined,也就是说,这个时候this指向的是b的做用域,而b中没有定义a,因此输出的是undefined 然而一切并非依靠想象,总有状况例外,咱们看下一个例子
例子7
var foo = {
a: 1,
b: {
a: 2,
fn: function() {
console.log(this) // window
console.log(this.a) // undefined
}
}
}
var tm = foo.b.fn
tm()
复制代码
从这个例子中咱们看到,this指向的是window,这是怎么回事?其实很好理解,还记得六字箴言吗?谁调用,指向谁
,这一句var tm = foo.b.fn
只是进行了赋值,把 fn
赋值给了全局变量 tm
,然而最终的调用时机是在 window做用域调用的函数 tm()
, 因此 this的指向是window对象。至此, this 的指向已经完毕
就六个字 谁调用,指向谁
,另加几个条件
非严格模式下,若是一个函数中有this,而且这个this没有被上一级调用,那么这个this的指向就是window
若是一个函数中有this,这个函数被上一级对象调用,那么this就指向上一级对象
若是一个函数有this,假如调用这个函数的有多级对象,那么this指向的是调用它的上一级对象
一般状况下,咱们想使用其它环境变相下的状态,这就须要借助this来实现,经常使用改变this指向的有如下几种方式能够实现
先看这个例子 例子8
function Foo () {
this.name = 'Justin'
}
var f = new Foo()
console.log(f.name) // Justin
复制代码
在使用 new 关键字调用构造函数时,会依次执行
prototype
赋值给这个新对象的 __proto__
假如函数中有 return, 来看看this的指向? 看下面这个例子 例子9
function Foo () {
this.name = 'Justin'
return {}
}
var f = new Foo()
console.log(f.name) // undefined
复制代码
在这里, 输出的是undefined,也就是说,this根本没有指向 f, 那么this到底指向哪里了呢 其实,若是一个返回值是对象,那么this指向的就是返回的对象, 若是反回的不是对象,那么指向的仍是指向函数的实例, null除外
例子10 利用下面几个例子验证
function Foo () {
this.name = 'Justin'
return function(){}
}
var f = new Foo()
console.log(f.name) // undefined
复制代码
例子11
function Foo () {
this.name = 'Justin'
return 1
}
var f = new Foo()
console.log(f.name) // Justin
复制代码
例子12
function Foo () {
this.name = 'Justin'
return undefined
}
var f = new Foo()
console.log(f.name) // Justin
复制代码
例子13
function Foo () {
this.name = 'Justin'
return null
}
var f = new Foo()
console.log(f.name) // Justin
复制代码
以上跟第三点总结相符合,至此,构造函数改变this指向解析完毕
例子13
var w = "流星火雨"
var obj = {
name: "黄忠",
w: this.w,
state: function(name, ow){
console.log(`${this.name} 的 w 技能是 ${this.w}`)
}
}
var skills = {
name: '马岱',
w: "紫电箭雨"
}
obj.state() // 忠 的 w 技能是 undefined
obj.state.call(skills) //马岱 的 w 技能是 紫电箭雨
obj.state.apply(skills) //马岱 的 w 技能是 紫电箭雨
obj.state.bind(skills) //马岱 的 w 技能是 紫电箭雨
复制代码
从上面看出来, call, apply, bind把this的指向改变为call, apply, bind所传入的第一个参数, 除此以外,他们是没有什么区别的
先看一个例子
var w = "流星火雨"
var obj = {
name: "黄忠",
w: this.w,
state: function(HeroType, HP){
console.log(`${this.name} 的 w 技能是 ${this.w}, 他是一个 ${HeroType}, 他的血量是${HP}`)
}
}
var skills = {
name: '马岱',
w: "紫电箭雨"
}
obj.state() // 忠 的 w 技能是 undefined
obj.state.call(skills, "法师", 100) //马岱 的 w 技能是 紫电箭雨
obj.state.apply(skills, ["法师", 100]) //马岱 的 w 技能是 紫电箭雨
obj.state.bind(skills, "法师", 100)() //马岱 的 w 技能是 紫电箭雨
复制代码
不一样的是, apply第二个参数接受的是一个数组, call 直接按参数排列就能够了,而 bind 跟call类似,只不事后面多了个 ()
最后,再加一个复杂的案例
function foo() {
let args = Array.prototype.slice.apply(arguments)
console.log("args", args) //[ '国家队', '黄忠', '典韦', '张莹莹', '黄盖', '许褚' ]
}
foo("国家队", "黄忠", "典韦", "张莹莹", "黄盖", "许褚")
复制代码
更多请参考: www.iquanku.com/admin/28.ht…