javascript基础十:说说你对Javascript中this对象的理解

这篇具有很好参考价值的文章主要介绍了javascript基础十:说说你对Javascript中this对象的理解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

javascript基础十:说说你对Javascript中this对象的理解
一、定义
函数的 this 关键字在 JavaScript 中的表现略有不同,此外,在严格模式和非严格模式之间也会有一些差别

在绝大多数情况下,函数的调用方式决定了 this 的值(运行时绑定)

this 关键字是函数运行时自动生成的一个内部对象,只能在函数内部使用,总指向调用它的对象

举个粟子:

function baz() {
    // 当前调用栈是:baz
    // 因此,当前调用位置是全局作用域
    
    console.log( "baz" );
    bar(); // <-- bar的调用位置
}

function bar() {
    // 当前调用栈是:baz --> bar
    // 因此,当前调用位置在baz中
    
    console.log( "bar" );
    foo(); // <-- foo的调用位置
}

function foo() {
    // 当前调用栈是:baz --> bar --> foo
    // 因此,当前调用位置在bar中
    
    console.log( "foo" );
}

baz(); // <-- baz的调用位置

同时,this在函数执行过程中,this一旦被确定了,就不可以再更改

var a = 10;
var obj = {
  a: 20
}

function fn() {
  this = obj; // 修改this,运行后会报错
  console.log(this.a);
}

fn();

二、绑定规则

根据不同的使用场合,this有不同的值,主要分为下面几种情况:

  • 默认绑定
  • 隐式绑定
  • new绑定
  • 显示绑定

默认绑定
全局环境中定义person函数,内部使用this关键字

var name = 'Jenny';
function person() {
    return this.name;
}
console.log(person());  //Jenny

上述代码输出Jenny,原因是调用函数的对象在游览器中位window,因此this指向window,所以输出Jenny

注意:
严格模式下,不能将全局对象用于默认绑定,this会绑定到undefined,只有函数运行在非严格模式下,默认绑定才能绑定到全局对象

隐式绑定

函数还可以作为某个对象的方法调用,这时this就指这个上级对象

function test() {
  console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;

obj.m(); // 1

这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象

var o = {
    a:10,
    b:{
        fn:function(){
            console.log(this.a); //undefined
        }
    }
}
o.b.fn();

上述代码中,this的上一级对象为b,b内部并没有a变量的定义,所以输出undefined

这里再举一种特殊情况


var o = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //undefined
            console.log(this); //window
        }
    }
}
var j = o.b.fn;
j();

此时this指向的是window,这里的大家需要记住,this永远指向的是最后调用它的对象,虽然fn是对象b的方法,但是fn赋值给j时候并没有执行,所以最终指向window

new绑定
通过构建函数new关键字生成一个实例对象,此时this指向这个实例对象

function test() {
 this.x = 1;
}

var obj = new test();
obj.x // 1

上述代码之所以能过输出1,是因为new关键字改变了this的指向

这里再列举一些特殊情况:
new过程遇到return一个对象,此时this指向为返回的对象

function fn()  
{  
    this.user = 'xxx';  
    return {};  
}
var a = new fn();  
console.log(a.user); //undefined

如果返回一个简单类型的时候,则this指向实例对象

function fn()  
{  
    this.user = 'xxx';  
    return 1;
}
var a = new fn;  
console.log(a.user); //xxx

注意的是null虽然也是对象,但是此时new仍然指向实例对象

function fn()  
{  
    this.user = 'xxx';  
    return null;
}
var a = new fn;  
console.log(a.user); //xxx

显示修改
apply()、call()、bind()是函数的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象。因此,这时this指的就是这第一个参数

var x = 0;
function test() {
 console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;
obj.m.apply(obj) // 1

关于apply、call、bind三者的区别,我们后面再详细说

三、箭头函数

在 ES6 的语法中还提供了箭头函语法,让我们在代码书写时就能确定 this 的指向(编译时绑定)

举个粟子:

const obj = {
  sayThis: () => {
    console.log(this);
  }
};

obj.sayThis(); // window 因为 JavaScript 没有块作用域,所以在定义 sayThis 的时候,里面的 this 就绑到 window 上去了
const globalSay = obj.sayThis;
globalSay(); // window 浏览器中的 global 对象

虽然箭头函数的this能够在编译的时候就确定了this的指向,但也需要注意一些潜在的坑

绑定事件监听

箭头函数的this指向是 父级程序的this指向
如果没有父级程序 或者 父级程序没有this ,箭头函数的this指向是 window

const button = document.getElementById('mngb');
button.addEventListener('click', ()=> {
    console.log(this === window) // true
    this.innerHTML = 'clicked button'
})

上述可以看到,我们其实是想要this为点击的button,但此时this指向了window

包括在原型上添加方法时候,此时this指向window

Cat.prototype.sayName = () => {
    console.log(this === window) //true
    return this.name
}
const cat = new Cat('mm');
cat.sayName()

同样的,箭头函数不能作为构建函数

四、优先级

隐式绑定 VS 显式绑定

function foo() {
    console.log( this.a );
}

var obj1 = {
    a: 2,
    foo: foo
};

var obj2 = {
    a: 3,
    foo: foo
};

obj1.foo(); // 2
obj2.foo(); // 3

obj1.foo.call( obj2 ); // 3
obj2.foo.call( obj1 ); // 2

显然,显示绑定的优先级更高

new绑定 VS 隐式绑定

function foo(something) {
    this.a = something;
}

var obj1 = {
    foo: foo
};

var obj2 = {};

obj1.foo( 2 );
console.log( obj1.a ); // 2

obj1.foo.call( obj2, 3 );
console.log( obj2.a ); // 3

var bar = new obj1.foo( 4 );
console.log( obj1.a ); // 2
console.log( bar.a ); // 4

可以看到,new绑定的优先级>隐式绑定

new绑定 VS 显式绑定

因为new和apply、call无法一起使用,但硬绑定也是显式绑定的一种,可以替换测试

function foo(something) {
    this.a = something;
}

var obj1 = {};

var bar = foo.bind( obj1 );
bar( 2 );
console.log( obj1.a ); // 2

var baz = new bar( 3 );
console.log( obj1.a ); // 2
console.log( baz.a ); // 3

bar被绑定到obj1上,但是new bar(3) 并没有像我们预计的那样把obj1.a修改为3。但是,new修改了绑定调用bar()中的this

我们可认为new绑定优先级>显式绑定

综上,new绑定优先级 > 显示绑定优先级 > 隐式绑定优先级 > 默认绑定优先级文章来源地址https://www.toymoban.com/news/detail-464007.html

到了这里,关于javascript基础十:说说你对Javascript中this对象的理解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JavaScript this对象

    this时是函数运行时自动生成的一个内部对象,只能在函数内部使用,总 指向调用它的对象 默认绑定 全局环境中定义函数,内部使用this 上述调用函数的对象在浏览器中为window,所以this指向window,输出Jenny 函数可以作为某个对象的方法来调用,此时this就指向这

    2024年03月11日
    浏览(27)
  • 说说你对栈、队列的理解?应用场景?

    栈(stack)又名堆栈,它是一种运算受限的线性表,限定仅在表尾进行插入和删除操作的线性表 表尾这一端被称为栈顶,相反地另一端被称为栈底,向栈顶插入元素被称为进栈、入栈、压栈,从栈顶删除元素又称作出栈 所以其按照先进后出的原则存储数据,先进入的数据被压

    2024年04月11日
    浏览(38)
  • 说说你对图的理解?相关操作有哪些?

    在计算机科学中,图是一种抽象的数据类型,在图中的数据元素通常称为结点, V 是所有顶点的集合, E 是所有边的集合 如果两个顶点 v , w ,只能由 v 向 w ,而不能由 w 向 v ,那么我们就把这种情况叫做一个从  v  到  w  的有向边。 v 也被称做初始点, w 也被称为终点。这

    2024年04月22日
    浏览(37)
  • 说说你对堆的理解?如何实现?应用场景?

    堆(Heap)是计算机科学中一类特殊的数据结构的统称 堆通常是一个可以被看做一棵完全二叉树的数组对象,如下图: 总是满足下列性质: 堆中某个结点的值总是不大于或不小于其父结点的值 堆总是一棵完全二叉树 堆又可以分成最大堆和最小堆: 最大堆:每个根结点,都有根

    2024年04月22日
    浏览(31)
  • this 之谜揭底:从浅入深理解 JavaScript 中的 this 关键字(二)

    系列首发于公众号『前端进阶圈』 ,若不想错过更多精彩内容,请“星标”一下,敬请关注公众号最新消息。 调用位置 在理解 this 的绑定过程之前,首先要理解 调用位置 : 调用位置就是函数在代码中被调用的位置(而不是声明的位置) 。 通常来说,寻找调用位置就是寻找

    2024年02月08日
    浏览(35)
  • 说说你对贪心算法、回溯算法的理解?应用场景?

    贪心算法,又称贪婪算法,是算法设计中的一种思想 其期待每一个阶段都是局部最优的选择,从而达到全局最优,但是结果并不一定是最优的 举个零钱兑换的例子,如果你有1元、2元、5元的钱币数张,用于兑换一定的金额,但是要求兑换的钱币张数最少 如果现在你要兑换

    2024年04月28日
    浏览(34)
  • 说说你对数据结构的理解?有哪些?区别?

    数据结构是计算机存储、组织数据的方式,是指相互之间存在一种或多种特定关系的数据元素的集合 前面讲到,一个程序 = 算法 + 数据结构,数据结构是实现算法的基础,选择合适的数据结构可以带来更高的运行或者存储效率 数据元素相互之间的关系称为结构,根据数据元

    2024年04月10日
    浏览(27)
  • 说说你对归并排序的理解?如何实现?应用场景?

    归并排序(Merge Sort)是建立归并操作上的一种有效,稳定的排序算法,该算法是采用分治法的一个非常典型的应用 将已有序的子序列合并,得到完全有序的序列,即先使每个子序列有序,再使子序列段间有序 例如对于含有  n  个记录的无序表,首先默认表中每个记录各为一

    2024年04月24日
    浏览(52)
  • 说说你对二分查找的理解?如何实现?应用场景?

      在计算机科学中,二分查找算法,也称折半搜索算法,是一种在有序数组中查找某一特定元素的搜索算法 想要应用二分查找法,则这一堆数应有如下特性: 存储在数组中 有序排序 搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束 如果

    2024年04月25日
    浏览(26)
  • 说说你对集合的理解?常见的操作有哪些?

    集合(Set),指具有某种特定性质的事物的总体,里面的每一项内容称作元素 在数学中,我们经常会遇到集合的概念: 有限集合:例如一个班集所有的同学构成的集合 无限集合:例如全体自然数集合 在计算机中集合道理也基本一致,具有三大特性: 确定性:于一个给定的

    2024年04月16日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包