资讯专栏INFORMATION COLUMN

js里this的几种用法

melody_lql / 2441人阅读

摘要:的几种用法关于是什么理论上是执行上下文的一个属性,的值在进入到执行上下文的时候就已经确定了,且不会再改变。默认绑定这种情况下,不属于任何一个函数方法内,即在全局作用域下,这种情况下称为默认绑定。最后的总结用伪代码的形式来表示例外例外本文参考

this的几种用法 关于this

this是什么?

理论上this是执行上下文的一个属性,this的值在进入到执行上下文的时候就已经确定了,且不会再改变。这一点很重要。

this的作用?

this 的机制提供了一个优雅的方式,隐式地传递一个对象,这可以让函数设计的更加简洁,并且复用性更好。

总览

new绑定,this指向由new创建的对象

显示绑定,this指向apply或者call函数的第一个参数

隐式绑定,this指向函数的调用者。

默认绑定,严格模式下指向undefinded,非严格模式this指向全局对象。

箭头函数绑定,this指向箭头函数外边包裹的普通函数

new绑定

当用new创建一个新的对象的时候,this指向了由new关键字声明创建的对象。

</>复制代码

  1. class Person(name){
  2. constructor(name){
  3. this.name = name;
  4. }
  5. showThis(){
  6. return this;
  7. }
  8. }
  9. var p1 = new Person("zhang");
  10. var p2 = new Person("zhao");
  11. console.log(p1.showThis() === p1); //true
  12. console.log(p2.showThis() === p2); //true
  13. console.log(p1.showThis() === Persion) //false

可以看到,这种情况下this的值指向了由new创建的对象的引用。this会被绑定到这个对象上去。

显式绑定

所谓的显式绑定,指的是通过apply或者call方法的第一个参数。

call和apply的不同,两个方法的第一个参数都是this赋给的对象。不同在于,之后的参数被当作call方法的形参依次传进去,而apply则是接受一个数组。

看代码:

</>复制代码

  1. function foo(){
  2. console.log(this === obj); //true
  3. console.log(this.a === 2); //true
  4. }
  5. var obj = {
  6. a:2
  7. }
  8. foo.call(obj);
隐式绑定

隐式绑定用的次数比较多。一个最重要的特点就是,this的指定顺序和在哪里定义没有关系,而是取决于调用者。

严格意义来说,this是上下文里的一个属性(存放各种变量的变量对象同样也是上下文里的属性),this的值总是指向当前上下文的父级上下文,其实也就是当前上下文的调用者。

看代码:

</>复制代码

  1. //第一个简单的例子
  2. var obj = {
  3. a : 1,
  4. foo : function(){
  5. console.log(this === obj); //trun
  6. console.log(this.a === 1); //true
  7. },
  8. bar : bar
  9. }
  10. //假如把一个属性定义在对象外边
  11. function bar(){
  12. console.log(this === obj); //true
  13. }
  14. obj.foo();
  15. obj.bar(); //都是true

再来一个例子

</>复制代码

  1. function bar(){
  2. console.log(this === obj1);
  3. console.log(this === obj2);
  4. }
  5. function foo(){
  6. console.log(this === obj1);
  7. console.log(this === obj2);
  8. }
  9. var obj1 = {
  10. bar: bar,
  11. foo: foo
  12. }
  13. var obj2 = {
  14. bar: obj1.bar,
  15. foo: obj1.foo,
  16. }
  17. obj1.foo(); //true false
  18. obj2.foo(); //false true
  19. obj1.bar(); //true false
  20. obj2.foo(); //false true

很简单,foo和bar两个方法分别由obj1和obj2调用,哪怕obj2中的foo和bar是obj1的也没关系,与在哪里定义没有关系,纯粹看是看谁调用的,obj2.foo()就是obj2调用的foo方法,所以,这个时候this指向obj2。

多说一句,如果既有显示绑定又有隐式绑定,当然是以显示绑定为准。

默认绑定

这种情况下,this不属于任何一个函数方法内,即在全局作用域下,这种情况下称为默认绑定。

非严格模式下,这个时候this值为window全局对象。

</>复制代码

  1. function foo(){
  2. console.log(this === window);
  3. }
  4. foo();

严格模式下,this的值是undefined

</>复制代码

  1. "use strict";
  2. function foo() {
  3. console.log( this === undefined );
  4. }
  5. foo(); // true
  6. foo.call(undefined); // true
  7. foo.call(null); // false
箭头函数

箭头函数其实是一个语法躺,箭头函数的里的this指向包裹箭头函数的那个函数的this值。很好理解。

</>复制代码

  1. // ES6
  2. function foo() {
  3. setTimeout(() => {
  4. console.log(this === obj); // true
  5. }, 100);
  6. }
  7. const obj = {
  8. a : 1
  9. }
  10. foo.call(obj);
  11. // ES5
  12. function foo() {
  13. var _this = this;
  14. setTimeout(function () {
  15. console.log(_this === obj); // true
  16. }, 100);
  17. }
  18. var obj = {
  19. a : 1
  20. }
  21. foo.call(obj);
最后的总结

用伪代码的形式来表示

</>复制代码

  1. if (`newObj = new Object()`) {
  2. this = newObj
  3. } else if (`bind/call/apply(thisArgument,...)`) {
  4. if (`use strict`) {
  5. this = thisArgument
  6. } else {
  7. if (thisArgument == null || thisArgument == undefined) {
  8. this = window || global
  9. } else {
  10. this = ToObject(thisArgument)
  11. }
  12. }
  13. } else if (`Function Call`) {
  14. if (`obj.foo()`) {
  15. // base value . Reference = base value + reference name + strict reference
  16. // 例外: super.render(obj). this = childObj ?
  17. this = obj
  18. } else if (`foo()`) {
  19. // 例外: with statement. this = with object
  20. this = `use strict` ? undefined : window || global
  21. }
  22. }

本文参考

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82374.html

相关文章

  • 判断是否是数组几种方法— (js基础复习第1期)

    摘要:如果网页中包含多个框架,那实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的构造函数。如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。 1. 首先,typeof肯定是不行的 对于一些基本类型,typeof是可以判断出数据类型,但是判断一些引用类型时候,不能具体到具体哪一种类型 再来复习一下typeof的...

    supernavy 评论0 收藏0
  • 返回顶部几种实现

    摘要:返回顶部这里初始状态的返回顶部为不可见,通过判断页面滚动高度切换显示隐藏,的样式可以自己设计。 showImg(https://segmentfault.com/img/bVGDef?w=1390&h=540); 返回顶部的按钮大家并不陌生,针对长滚动条的信息流页面添加返回顶部的按钮可以给用户良好的体验,而返回顶部的实现也是多种多样,本文分享几个案例并给出评价 作为引子讲一个常用的案例...

    SillyMonkey 评论0 收藏0
  • 返回顶部几种实现

    摘要:返回顶部这里初始状态的返回顶部为不可见,通过判断页面滚动高度切换显示隐藏,的样式可以自己设计。 showImg(https://segmentfault.com/img/bVGDef?w=1390&h=540); 返回顶部的按钮大家并不陌生,针对长滚动条的信息流页面添加返回顶部的按钮可以给用户良好的体验,而返回顶部的实现也是多种多样,本文分享几个案例并给出评价 作为引子讲一个常用的案例...

    silvertheo 评论0 收藏0
  • 前端面经整理之JS和CSS

    摘要:作为对象原型链的终点。调用函数时,应该提供的参数没有提供,该参数等于。它可以用于引用该函数的函数体内当前正在执行的函数。 一 JS 二 CSS 一 JS ==和===的区别 ===叫做严格运算符 ==叫做相等运算符严格运算符比较时不仅仅比较数值还要比较数据类型是否一样相等运算符在比较相同类型的数据时,与严格相等运算符完全一样。 在比较不同类型的数据时,相等运算符会先将数据进行类型转换,...

    stonezhu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<