javascript中this指向四个基本场景
- 显式绑定,指向绑定对象(call、apply、bind)
- 隐式绑定,指向归属属性
- new 绑定指向实例
- 默认指向全局
一、显式绑定
显式绑定,this的指向比较明确(例如:call、apply、bind等)
var a = 'test '
function foo() {
console.log('---foo---', this , this.a)
}
const obj = {
a:'obj'
}
foo.call(obj) // this => obj对象。 this.a => obj.a
复制代码
「问题1」「 如果是foo.call(null), this => 指的对象是什么呢? this.a => 展示的值是什么呢? 」
二、 隐式绑定
隐式绑定常常出现在链式调用中,this总是指向调用它的对象
var a = 'test '
function foo() {
console.log('---foo---', this , this.a)
}
const obj = {
a:'obj',
foo:foo,
foo2:{
a:'foo2',
foo:foo
}
}
obj.foo()
// ---foo--- {a: "obj", foo2: {…}, foo: ƒ} obj
// this => {a: "obj", foo2: {…}, foo: ƒ} this.a => obj
obj.foo2.foo()
// ---foo--- {a: "foo2", foo: ƒ} foo2
// this => {a: "foo2", foo: ƒ} this.a => foo2
const objFoo = obj.foo;
复制代码
- 上面「obj.foo」的调用中,foo的this指向它的调用对象,即obj对象
- 「obj.foo2.foo」的调用中,foo的this指向的是foo2
「问题2」「执行objFoo(),返回的结果又是什么呢?」
三、new绑定
new绑定的原理其实和显式绑定有一定关系。看下实现new的四步走就明白了
function bar(){
console.log('---bar---', this , this.a)
}
const fn = new bar();
// ---bar--- bar {} undefined
// this => fn 即Object.create(bar.prototype)
复制代码
四、默认绑定
当不符合上面的情况的时候,就应该考虑是不是默认绑定全局对象了
问题1
var a = 'test '
function foo() {
console.log('---foo---', this, this.a)
}
const obj = {
a: 'obj'
}
foo.call(null)
// ---foo--- Window {window: Window, self: Window, document: document, name: "", location: Location, …} test
// this => window. this.a => test
复制代码
虽然foo显式指定指向了null,显式绑定的方法中会做非空判断,如果不存在便指向当前的上下文对象。
问题2
var a = 'test '
function foo() {
console.log('---foo---', this , this.a)
}
const obj = {
a:'obj',
foo:foo,
foo2:{
a:'foo2',
foo:foo
}
}
const objFoo = obj.foo;
objFoo()
// ---foo--- Window {window: Window, self: Window, document: document, name: "", location: Location, …} test
this => window. this.a => test
复制代码
为什么这次明明使用了obj.foo还是指向默认绑定呢?
答案:obj.foo指向的是foo的引用地址,此时把这个引用地址赋值给了objFoo,等价于 「const objFoo = foo」,而此时调用 「objFoo()」 和直接调用 「foo()」 是等价的,都使用了默认绑定
「参数的形式」
var a = 'test '
function foo() {
console.log('---foo---', this, this.a)
}
function bar(fn) {
fn()
}
const obj = {
a:'obj',
foo:foo
}
bar(foo)
bar(obj.foo)
// foo 还是 obj.foo 传递的都是引用地址
// this都是指向全局上下文对象
复制代码
「多层嵌套」
var a = 'test '
function foo() {
console.log('---foo---', this, this.a)
}
function bar() {
function barch(){
foo()
function barchch(){
foo()
}
barchch()
}
barch()
}
bar()
// this => window
复制代码
规则小记
❝
「this指向可以总结为:有绑定指向绑定对象,有归属指向归属对象,有new指向实例对象,其他指向上下文对象」
❞
箭头函数
❝
使用es6中的箭头函数
var a = 'global => a '
const obj = {
a:'ojb => a',
foo: () => {
console.log('foo:',this.a)
},
boo:function(){
console.log('boo:',this.a)
}
}
obj.foo()
// this => window this.a => 'global => a'
// 箭头函数没有this, 所以foo的this使用的是其父层obj的this,根据上面?规则obj没有显示绑定,也不归属其他对象,非new的实例对象,只能使用默认指向当前上下文对象了
obj.boo()
// this => obj this.a => 'obj => a'
// 还是?上面的规则对比,boo没有显示绑定,但是是obj链式调用,在执行的属于obl的属性,则boo的this指向了obj,所以this.a = obj.a
复制代码❞
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END