this-动态作使用域?

作者 : 开心源码 本文共2417个字,预计阅读时间需要7分钟 发布时间: 2022-05-11 共96人阅读

JavaScript中的作使用域是词法作使用域,但它的另一个重要机制 this 是动态作使用域的表亲。this提供了一种更优雅的方式来隐式传递一个对象的引使用(自动引使用合适的上下文对象),使得我们能将API设计得更加简洁和易于复使用。
函数执行环境包含函数的调使用栈、调使用方法、传入参数等信息,this就是其中一个属性。

this 既不指向函数自身也不指向函数的词法作使用域

1 this 绑定规则

在严格模式下,this = undefined

this 是在运行时确定的,并不是在编写时确定。它的上下文取决于函数调使用时的各种条件。 this 的绑定和函数公告的位置没有任何关系,只取决于函数的调使用方式。

分析函数的调使用位置最重要的是要分析调使用栈(就是为了到达当前执行位置所调使用的所有函数)。我们关心的调使用位置就在当前正在执行的函数的前一个调使用中。
调使用位置决定 this 的绑定对象遵循四条规则:

1.1 隐式绑定

对象的一个属性指向函数,并通过这个属性调使用函数,从而把 this 绑定到这个对象上。

var a = {  f: function(){console.log(this)}}a.f() // this指向afunction bf(){console.log(this)} var b = {f: bf}b.f() // this指向b

各种嵌套情况:

//对象的对象的方法var a = { b: {  f: function(){console.log(this)} }   }a.b.f() // this指向b{f: ?}
//对象的方法的内部函数var a = { b: function(){  (function(){console.log(this)})() }   }undefineda.b() //this指向window;由于在调使用栈中匿名函数前一个是b函数

1.2 call()/apply()/bind()

ES5 中提供了内置的方法 Function.prototype.
bind ,使用来显式绑定this:

function foo(something) {  console.log( this);}foo.bind({})() //this 指向 {}//实现原理如下Function.prototype.bind(obj, arguments ) {  var foo = this  return function() {    return foo.apply( obj, arguments );  };}

假如你把 null 或者者 undefined 作为 this 的绑定对象传入 call 、 apply 或者者 bind ,这些值
在调使用时会被忽略,实际应使用的是默认绑定规则

bind()函数在 ECMA-262 第五版才被加入;它可可以无法在所有浏览器上运行。你能部份地在脚本开头加入以下代码,就可以使它运作,让不支持的浏览器也可以用 bind() 功可以。

if (!Function.prototype.bind) {  Function.prototype.bind = function(oThis) {    if (typeof this !== 'function') {      // closest thing possible to the ECMAScript 5      // internal IsCallable function      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');    }    var aArgs   = Array.prototype.slice.call(arguments, 1),        fToBind = this,        fNOP    = function() {},        fBound  = function() {          return fToBind.apply(                  //判断能否用new操作符调使用此函数                  this instanceof fNOP ? this : oThis,                 // 获取调使用时(fBound)的传参.bind 返回的函数入参往往是这么传递的                 aArgs.concat(Array.prototype.slice.call(arguments)));        };    // 维护原型关系    if (this.prototype) {      // Function.prototype doesn't have a prototype property      fNOP.prototype = this.prototype;     }    fBound.prototype = new fNOP();    return fBound;  };}

上述算法和实际的实现算法还有许多其余的不同 (虽然可可以还有其余不同之处,却没有那个必要去穷尽):

  • 这部分实现依赖于Array.prototype.slice()Array.prototype.concat()Function.prototype.call()这些原生方法。
  • 这部分实现创立的函数的实现并没有caller 以及会在 get,set或者者deletion上抛出TypeError错误的 arguments 属性这两个不可改变的“毒药” 。(如果环境支持{jsxref(“Object.defineProperty”)}}, 或者者实现支持__defineGetter__ and __defineSetter__ 扩展)
  • 这部分实现创立的函数有 prototype 属性。(正确的绑定函数没有的)
  • 这部分实现创立的绑定函数所有的 length 属性并不是同ECMA-262标准一致的:它的 length 是0,而在实际的实现中根据目标函数的 length 和预先指定的参数个数可可以会返回非零的 length。

1.3 new绑定

用 new 来调使用函数,或者者说发生构造函数调使用时,会自动执行下面的操作。

  1. 创立(或者者说构造)一个全新的对象。
  2. 这个新对象会被执行 [[ 原型 ]] 连接。
  3. 这个新对象会绑定到函数调使用的 this 。
  4. 假如函数没有返回其余对象,那么 new 表达式中的函数调使用会自动返回这个新对象。

1.4 默认规则
无法用上述各项规则时;this 指向全局对象

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » this-动态作使用域?

发表回复