JS中如何精简理解函数的this指向?

2026-05-17 00:501阅读0评论SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1359个文字,预计阅读时间需要6分钟。

JS中如何精简理解函数的this指向?

从原理出发,首先我们围绕this能力进行详细探讨。this最终指向它的调用者。这句话看似简单,但深入理解其背后的执行原理才能更好地解决问题。

从原理出发

首先我们围绕耳熟能详的“this始终指向它的调用者”开始。这句结论虽然没有什么问题,但是说得过于笼统,还是得深入到背后的执行原理才能举一反三解决问题。

举个简单的例子:

var obj = { num: 2; foo: function () { console.log(this.num) } }; var foo = obj.foo; var num = 3; obj.foo();//2 foo();//3

obj.foo();是对象obj调用自身的属性(方法)foothis指向调用者obj
②由var foo = obj.foo;获取函数,并用foo();在全局作用域中调用函数,所以this指向浏览器全局对象Window

内存数据结构的概述

JS之所以设计this,是因为其内存的数据结构的特征。

JS中如何精简理解函数的this指向?

var obj = { foo: 5 };

①上面的对象赋值给变量,其实质是JS引擎现在内存中生成{foo: 5},然后再把该对象的内存地址赋值给变量obj。也就是说onj.foo实质上是先从obj获取对象的内存地址然后再从地址读取原始对象,最后返回对象属性foo的值。
②原始对象以词典结构保存,一个属性名对应一个属性描述对象。如下图,foo属性的描述对象就包含4个描述属性,而最重要的值保存在描述对象[[value]]中。

foo属性值为函数时,JS引擎同样会先将原始函数保存在内存中,然后把该函数的内存地址存放于foo属性的描述对象中的[[value]]里面。

从原理出发章节参考于JavaScript 的 this 原理——阮一峰的网络日志

为何造就this

我们需要JS在函数体内部可以引用当前环境的其他内部变量,就像这样:

var f = function () {- console.log(this.x)//内部引用当前调用者变量x }; var x = 1;//实质给全局对象Window添加属性 x 并赋值 1 var obj = { x: 2,//调用者内部变量 f: f } f();//结果为1,执行于全局环境,所以 this.x 指向 Window.x boj.f();//结果为2,执行于 obj 内部环境,所以 this.x 指向 obj.x

这就说明了造就this的目的就是为函数内部的语句指定当前运行环境,而当前运行环境不一定就是该函数内部环境哈。

this的扩展延伸 构造函数与this

function name () { this.fne = "yulin" }; var a = new name(); console.log(a.fne);//yulin

关于这个构造函数这里先笼统提一些,new关键字会创建一个空对象name { },并且会将函数name()的保留在[[Prototype]]原型中而且会执行该函数并返回执行结果(这里有几种情况下文会提到),最后整个对象name { }赋值给变量aa即是对象实例。所以this.fne指向a.fne

thisreturn的问题

上文说到构造函数执行的返回结果的有几种情况:

  1. 返回对象时,this会指向返回的对象,null除外,否则指向起始调用者。

function name () { this.fne = "yulin"; return {} }; var a = new name(); console.log(a.fne);//undefined,指向 {} function name () { this.fne = "yulin"; return function () {} }; var a = new name(); console.log(a.fne);//undefined,指向 function () {} function name () { this.fne = "yulin"; return null }; var a = new name(); console.log(a.fne);//yulin,指向 null,null是特殊的对象不会更改 this function name () { this.fne = "yulin"; return undefined }; var a = new name(); console.log(a.fne);//yulin,指向 name {} 更灵活的this指向方法

  1. 当我们需要在a对象中调用b对象的方法时,我们就需要用到call()方法指定目的运行环境。

const a = { name: 'yulin', fn: function (e, q) { console.log(this.name); console.log(e + q); } }; const b = { name: 'yhh' } var x = a.fn x.call(b, 2, 3);//yhh 5

  1. apply()方法与call()类型,但传入apply的第二个参数必须是数组,就像[1, 2, 3], [a , b, c]以及数组变量。

const a = { name: 'yulin', fn: function (e, q) { console.log(this.name); console.log(e + q); } }; const b = { name: 'yhh' } var x = a.fn x.apply(b, [2, 3]);//yhh 5 /* 以下代码效果一样 let arr = [2, 3]; x.apply(b, arr); */

请注意:a.call(null)a.apply(null)this指向都是Window
3. bind()call(), apply()完全不同,bind()改变this指向的同时还返回被调用的属性,方法。

const a = { name: 'yulin', fn: function (e, q) { console.log(this.name); console.log(e + q); } }; const b = { name: 'yhh' } var x = a.fn x.bind(b); /*ƒ (e, q) { console.log(this.name); console.log(e + q); }*/ let y = x.bind(b); y(2, 3);//yhh 5

本文共计1359个文字,预计阅读时间需要6分钟。

JS中如何精简理解函数的this指向?

从原理出发,首先我们围绕this能力进行详细探讨。this最终指向它的调用者。这句话看似简单,但深入理解其背后的执行原理才能更好地解决问题。

从原理出发

首先我们围绕耳熟能详的“this始终指向它的调用者”开始。这句结论虽然没有什么问题,但是说得过于笼统,还是得深入到背后的执行原理才能举一反三解决问题。

举个简单的例子:

var obj = { num: 2; foo: function () { console.log(this.num) } }; var foo = obj.foo; var num = 3; obj.foo();//2 foo();//3

obj.foo();是对象obj调用自身的属性(方法)foothis指向调用者obj
②由var foo = obj.foo;获取函数,并用foo();在全局作用域中调用函数,所以this指向浏览器全局对象Window

内存数据结构的概述

JS之所以设计this,是因为其内存的数据结构的特征。

JS中如何精简理解函数的this指向?

var obj = { foo: 5 };

①上面的对象赋值给变量,其实质是JS引擎现在内存中生成{foo: 5},然后再把该对象的内存地址赋值给变量obj。也就是说onj.foo实质上是先从obj获取对象的内存地址然后再从地址读取原始对象,最后返回对象属性foo的值。
②原始对象以词典结构保存,一个属性名对应一个属性描述对象。如下图,foo属性的描述对象就包含4个描述属性,而最重要的值保存在描述对象[[value]]中。

foo属性值为函数时,JS引擎同样会先将原始函数保存在内存中,然后把该函数的内存地址存放于foo属性的描述对象中的[[value]]里面。

从原理出发章节参考于JavaScript 的 this 原理——阮一峰的网络日志

为何造就this

我们需要JS在函数体内部可以引用当前环境的其他内部变量,就像这样:

var f = function () {- console.log(this.x)//内部引用当前调用者变量x }; var x = 1;//实质给全局对象Window添加属性 x 并赋值 1 var obj = { x: 2,//调用者内部变量 f: f } f();//结果为1,执行于全局环境,所以 this.x 指向 Window.x boj.f();//结果为2,执行于 obj 内部环境,所以 this.x 指向 obj.x

这就说明了造就this的目的就是为函数内部的语句指定当前运行环境,而当前运行环境不一定就是该函数内部环境哈。

this的扩展延伸 构造函数与this

function name () { this.fne = "yulin" }; var a = new name(); console.log(a.fne);//yulin

关于这个构造函数这里先笼统提一些,new关键字会创建一个空对象name { },并且会将函数name()的保留在[[Prototype]]原型中而且会执行该函数并返回执行结果(这里有几种情况下文会提到),最后整个对象name { }赋值给变量aa即是对象实例。所以this.fne指向a.fne

thisreturn的问题

上文说到构造函数执行的返回结果的有几种情况:

  1. 返回对象时,this会指向返回的对象,null除外,否则指向起始调用者。

function name () { this.fne = "yulin"; return {} }; var a = new name(); console.log(a.fne);//undefined,指向 {} function name () { this.fne = "yulin"; return function () {} }; var a = new name(); console.log(a.fne);//undefined,指向 function () {} function name () { this.fne = "yulin"; return null }; var a = new name(); console.log(a.fne);//yulin,指向 null,null是特殊的对象不会更改 this function name () { this.fne = "yulin"; return undefined }; var a = new name(); console.log(a.fne);//yulin,指向 name {} 更灵活的this指向方法

  1. 当我们需要在a对象中调用b对象的方法时,我们就需要用到call()方法指定目的运行环境。

const a = { name: 'yulin', fn: function (e, q) { console.log(this.name); console.log(e + q); } }; const b = { name: 'yhh' } var x = a.fn x.call(b, 2, 3);//yhh 5

  1. apply()方法与call()类型,但传入apply的第二个参数必须是数组,就像[1, 2, 3], [a , b, c]以及数组变量。

const a = { name: 'yulin', fn: function (e, q) { console.log(this.name); console.log(e + q); } }; const b = { name: 'yhh' } var x = a.fn x.apply(b, [2, 3]);//yhh 5 /* 以下代码效果一样 let arr = [2, 3]; x.apply(b, arr); */

请注意:a.call(null)a.apply(null)this指向都是Window
3. bind()call(), apply()完全不同,bind()改变this指向的同时还返回被调用的属性,方法。

const a = { name: 'yulin', fn: function (e, q) { console.log(this.name); console.log(e + q); } }; const b = { name: 'yhh' } var x = a.fn x.bind(b); /*ƒ (e, q) { console.log(this.name); console.log(e + q); }*/ let y = x.bind(b); y(2, 3);//yhh 5