JS - this指向

一、什么是this

A function's this keyword behaves a little differently in JavaScript compared to other languages. It also has some differences between strict mode and non-strict mode.

从官方文档我们可知

  • this是一个关键字
  • this主要用在函数中
  • this 在strict mode下指向有一些不同

1.1 全局环境

无论是否在strict mode,在全局执行环境中(在任何函数体外部)this 都指向全局对象。(浏览器中window为ECMAscript规定的Global对象)

"use strict"
//在 Node 中
console.log(this) // {}

//在浏览器中
console.log(this) //window
console.log(this === window) //true
this.foo = "foo"
console.log(window.foo) //foo
window.bar = "bar"
console.log(this.bar) //bar
1.1.1执行上下文(Execution Context)

在全局作用域var关键字声明变量和省略声明的变量都会添加为全局对象的属性

var foo = "foo"
bar = "bar"
this.foo  // foo
this.bar  // bar

const 、let 关键字声明的变量有自己的作用域

const foo = "foo"
let bar = "bar"
this.foo  // undefined
this.bar  // undefined

1.2 函数(运行内)环境

在函数内部,this的指向取决于函数被调用的方式。

1.2.1函数简单调用
//非严格模式下  this 的值默认指向全局对象。
function foo() {
  return this
}
// 在Node 中
foo() // Object [global]

//在浏览器中
foo() //window
//严格模式下 this 默认为undefined。
function foo() {
  "use strict"
  return this
}
// 在Node 中
foo() // undefined

//在浏览器中
foo() // undefined
1.2.2 函数作为对象的方法调用

(1) 当函数作为方法被调用时, this 指向调用该方法的对象

var foo = {
  fn:function(){
    return this
  }
}
foo.fn() // foo
var foo = {}
function fn() {
  return this
}
foo.fn = fn
foo.fn() // foo

(2) 链式调用,this指向上一个绑定对象

var bar = {
  fn:function(){
    return this
  }
}
var foo = {
  bar : bar
}
foo.bar.fn() // this ->bar

(3)当函数调用时没有绑定任何对象,隐式丢失

// 隐式丢失
var foo = {
  fn:function(){
    return this
  }
}
var bar = foo.fn 
bar() // window

二、this与箭头函数

2.1 箭头函数中,this与最近作用域的this相同

var foo = {
  fn: function () {
    return () => {
      return this
    }
  },
}
var bar = foo.fn()
bar() // this -> foo

fn函数返回一个匿名箭头函数,箭头函数中的this向上一层级找,此时箭头函数中的this = fn中的this

2.2 对象的方法中的箭头函数

var foo = {
  bar : this,
  fn :() => {
    return this
  }
}
foo.bar // window
foo.fn() //window

此时fn函数虽然作为foo的方法调用,但由于箭头函数向上找作用域this的缘故,箭头函数的this指向window

三、this与匿名函数

this对象是基于函数的运行环境绑定的
因为匿名函数的执行环境有全局性,因此this对象常指向window

var foo = {
  fn: function () {
    return function () {
      return this
    }
  },
}
foo.fn()() // this -> window

为什么匿名函数作用域的this没有访问外部作用域fn中的this呢?
因为函数在调用时会自动取得两个特殊的变量,this和arguments,匿名函数本身也会取得指向window的this,一旦搜得其活动对象即停止.

那么如何访问fn中的this呢

3.1 通过闭包保存

var foo = {
  fn: function () {
    var _this = this
    return function () {
      return _this
    }
  },
}
foo.fn()() // _this -> foo

3.2 通过箭头函数访问外部作用域

var foo = {
  fn: function () {
    return () => {
      return this
    }
  },
}
foo.fn()() // this -> foo

四、this与call()和apply()

可以通过使用函数继承自Function.prototype的call或 apply 方法将 this值绑定到调用中的特定对象。

var foo = {}
var args = []
function bar(...args) {
  return this
}
bar.call(foo,...args) // this -> foo
bar.apply(foo,args) // this -> foo

call和apply的区别为,call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组。

五、this与bind()

ECMAScript 5 引入了 Function.prototype.bind()。调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的。

var obj = {}
function bar (){
  return this
}
var foo = bar.bind(obj)
foo() // this -> obj
obj.foo = foo 
obj.foo() //this -> obj

六、this与getter和setter

当函数在一个 getter 或者 setter 中被调用。用作 getter 或 setter 的函数都会把 this 绑定到设置或获取属性的对象。

var foo = {}
Object.defineProperty(foo ,'bar',{
  get(){
    return this
  }
})
foo.bar // this -> foo

七、this与构造函数

当一个函数用作构造函数时(使用new关键字),this被绑定到构造的新对象。

function foo(why) {
  this.why = why
}
var bar = new foo("why")
bar.why // -> why

八、this与DOM事件处理函数

绝大部分浏览器,当函数被用作事件处理函数时,它的this指向触发事件的元素

var btn = document.getElementsByClassName("btn")
for (var i = 0; i < btn.length; i++) {
  btn[i].addEventListener('click',()=>{
    return this
  })
}
// this ->btn[i]

总结

非严格模式下,浏览器中

  • 函数外this指向window
  • 函数内this指向取决于调用方式
  • 箭头函数this指向向上一层作用域的this
  • 匿名函数this指向window
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353