ITPub博客

首页 > 大数据 > 数据分析 > 剖析 javascript 的 this 关键字

剖析 javascript 的 this 关键字

数据分析 作者:xingfafng 时间:2019-05-20 18:02:06 0 删除 编辑

this的定义


  https://www.ryw168.com/news/cases/14915.html


  表示当前执行代码的环境对象


  因此可将this的剖析分为“全局环境”和“函数环境”两种类型的环境对象


  全局环境


  console.log(this===window);//true


  vara=10;


  console.log(this.a);//10


  函数环境


  在函数内部,this的取值取决于函数被调用时的运行环境。


  这里涉及到内存里的数据结构相关的知识点,当我们定义以下字面量对象时会发生一系列的关联关系


  varobj={name:'Tom'};


  javascript引擎会先在内存中生成{name:'Tom'}对象,接着再把这个对象的内存地址赋值给obj变量,所以obj变量保存的只是一个内存地址而已,如果要获取obj.name,javascript引擎会先从obj变量中拿到内存地址,然后从该地址中获取原始对象,再返回name属性。


  而属性值为函数时,该函数会被保存在内存中,然后将该内存地址赋值给该属性,因此该地址赋值给不同环境执行时它的作用域是不一样的,而this对象就是指向函数当前的执行环境对象,执行环境是会在EventLoop(事件循环)过程中变化的,因此this在函数环境下是属于运行时的。


  varname='Tom';


  varobj={


  name:'Iceberg',


  say:function(){


  console.log('mynameis'+this.name);


  },


  sub:{


  say:function(){


  console.log('mynameis'+this.name);


  }


  }


  };


  obj.say();//mynameisIceberg


  obj.sub.say()//mynameisundefined;


  varsay=obj.say;


  say();//mynameisTom;


  上面的例子说明obj.say()执行环境为obj对象,而obj.sub.say()的执行环境却是obj.sub对象,而对于obj.sub来说并没有name属性,因此为undefined;而varsay=obj.say;则表示将say方法的内存地址赋值给全局变量,因此从全局变量name中取值。


  运用场景


  接下来从this在函数环境下的不同运用场景来剖析


  事件回调函数


  varhandler={


   nickname:'anonymous',


   register:function(){


   console.log(this.nickname);


   }


  }


  $('#registerBtn').on('click',handler.register);//undefined


  以上逻辑点击触发后输出的是undefined,因为函数被当做事件触发的回调函数执行时,this是指向该触发事件对应的元素,如要this仍然以handler对象为执行环境,则可使用函数的bind方法进行执行环境对象的绑定操作。


  $('#registerBtn').on('click',handler.register.bind(handler));//anonymous


  在react中经常需要在回调函数中调用this.state、this.props,按照上面的分析,将当前环境对象bind到回调函数中即可。


  如果是使用的箭头函数定义回调函数即可无需bind,因为箭头函数中this就是对应定义时所在的对象。


  构造函数


  要理解this在构造函数中的逻辑就要理清楚构造函数在实例化过程中都发生了什么。


  functionA(){


  this.name='Tom';


  this.age=20;


  }


  vara=newA();


  使用new命令实例化构造函数A的过程中会发生以下流程


  创建一个空对象,作为将要返回的对象实例


  将该空对象的原型指向构造函数的prototype属性


  将该空对象赋值给构造函数内部的this关键字


  执行构造函数内部代码


  默认返回this对象(如return的为非对象类型,如数字123,会被忽略进而默认returnthis对象)


  由以上逻辑可知道this关键字在构造函数中表示的是其实例对象。


  bind


  bind方法将函数体中的this指向新对象并返回一个新函数


  functionA(){

https://www.ryw168.com/news/cases/14912.html

  this.nickname='Tom';


  this.say=function(){


  console.log(this.nickname);


  }


  }


  varb={nickname:'John'};


  vara=newA();


  varsay=a.say;


  varsay1=a.say.bind(a);


  varsay2=a.say.bind(b);


  say();//undefined

https://www.ryw168.com/news/cases/14913.html

  say1();//Tom


  say2();//John


  call&apply


  call方法是指Function.prototype.call,因此每个函数都会具备call方法,fun.call(thisArg,arg1,arg2,...),call方法接收的第一个参数会替换原有的this指向的执行环境对象。


  functionA(){


  this.name='Tom';


  this.sayName=function(){


  console.log(this.name);


  };


  }


  functionB(){


  this.name='John';


  }


  vara=newA();


  a.sayName.call(newB());//John


  而apply方法与call的区别仅在于call接收参数列表而apply接收数组参数或者类数组对象(如函数的arguments对象)。


  总结


  由于javascript的EventLoop原理,决定了执行上下文会不断变化,因此this对象诞生于表达当前的执行环境对象。


   https://www.ryw168.com/news/cases/14914.html


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31554700/viewspace-2644995/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 没有了~
请登录后发表评论 登录
全部评论

注册时间:2019-05-20

  • 博文量
    4
  • 访问量
    6702