位置: 编程技术 - 正文

深入浅析JavaScript系列(13):This? Yes,this!(javascrip语言)

编辑:rootadmin

推荐整理分享深入浅析JavaScript系列(13):This? Yes,this!(javascrip语言),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:javascrip的特点有哪些?,深入浅析是什么意思,什么是javascrip,java script,深入浅析是什么意思,javascrip的特点有哪些?,java script,java script,内容如对您有帮助,希望把文章链接给更多的朋友!

前言

在这篇文章里,我们将讨论跟执行上下文直接相关的更多细节。讨论的主题就是this关键字。实践证明,这个主题很难,在不同执行上下文中this的确定经常会发生问题。

许多程序员习惯的认为,在程序语言中,this关键字与面向对象程序开发紧密相关,其完全指向由构造器新创建的对象。在ECMAScript规范中也是这样实现的,但正如我们将看到那样,在ECMAScript中,this并不限于只用来指向新创建的对象。

英文翻译: Dmitry A. Soshnikov在Stoyan Stefanov的帮助下发布: -- Dmitry A. Soshnikov修正: Zeroglif发布: --; 更新:-- = { VO: {...}, this: thisValue};

这里VO是我们前一章讨论的变量对象。

this与上下文中可执行代码的类型有直接关系,this值在进入上下文时确定,并且在上下文运行期间永久不变。

下面让我们更详细研究这些案例:

全局代码中的this

在这里一切都简单。在全局代码中,this始终是全局对象本身,这样就有可能间接的引用到它了。

// 显示定义全局对象的属性this.a = ; // global.a = alert(a); // // 通过赋值给一个无标示符隐式b = ;alert(this.b); // // 也是通过变量声明隐式声明的// 因为全局上下文的变量对象是全局对象自身var c = ;alert(this.c); //

函数代码中的this

在函数代码中使用this时很有趣,这种情况很难且会导致很多问题。

这种类型的代码中,this值的首要特点(或许是最主要的)是它不是静态的绑定到一个函数。

正如我们上面曾提到的那样,this是进入上下文时确定,在一个函数代码中,这个值在每一次完全不同。

不管怎样,在代码运行时的this值是不变的,也就是说,因为它不是一个变量,就不可能为其分配一个新值(相反,在Python编程语言中,它明确的定义为对象本身,在运行期间可以不断改变)。

那么,影响了函数代码中this值的变化有几个因素:

首先,在通常的函数调用中,this是由激活上下文代码的调用者来提供的,即调用函数的父上下文(parent context )。this取决于调用函数的方式。

为了在任何情况下准确无误的确定this值,有必要理解和记住这重要的一点。正是调用函数的方式影响了调用的上下文中的this值,没有别的什么(我们可以在一些文章,甚至是在关于javascript的书籍中看到,它们声称:“this值取决于函数如何定义,如果它是全局函数,this设置为全局对象,如果函数是一个对象的方法,this将总是指向这个对象。?这绝对不正确”)。继续我们的话题,可以看到,即使是正常的全局函数也会被调用方式的不同形式激活,这些不同的调用方式导致了不同的this值。

有可能作为一些对象定义的方法来调用函数,但是this将不会设置为这个对象。

那么,调用函数的方式如何影响this值?为了充分理解this值的确定,需要详细分析其内部类型之一——引用类型(Reference type)。

引用类型(Reference type)

使用伪代码我们可以将引用类型的值可以表示为拥有两个属性的对象——base(即拥有属性的那个对象),和base中的propertyName 。

引用类型的值只有两种情况:

1. 当我们处理一个标示符时

2. 或一个属性访问器

标示符的处理过程在下一篇文章里详细讨论,在这里我们只需要知道,在该算法的返回值中,总是一个引用类型的值(这对this来说很重要)。

标识符是变量名,函数名,函数参数名和全局对象中未识别的属性名。例如,下面标识符的值:

在操作的中间结果中,引用类型对应的值如下:

为了从引用类型中得到一个对象真正的值,伪代码中的GetValue方法可以做如下描述:

内部的[[Get]]方法返回对象属性真正的值,包括对原型链中继承的属性分析。

属性访问器都应该熟悉。它有两种变体:点(.)语法(此时属性名是正确的标示符,且事先知道),或括号语法([])。

在中间计算的返回值中,我们有了引用类型的值。

深入浅析JavaScript系列(13):This? Yes,this!(javascrip语言)

引用类型的值与函数上下文中的this值如何相关?——从最重要的意义上来说。 这个关联的过程是这篇文章的核心。 一个函数上下文中确定this值的通用规则如下:

在一个函数上下文中,this由调用者提供,由调用函数的方式来决定。如果调用括号()的左边是引用类型的值,this将设为引用类型值的base对象(base object),在其他情况下(与引用类型不同的任何其它属性),这个值为null。不过,实际不存在this的值为null的情况,因为当this的值为null的时候,其值会被隐式转换为全局对象。注:第5版的ECMAScript中,已经不强迫转换成全局变量了,而是赋值为undefined。

我们看看这个例子中的表现:

我们看到在调用括号的左边是一个引用类型值(因为foo是一个标示符)。

相应地,this也设置为引用类型的base对象。即全局对象。同样,使用属性访问器:

我们再次拥有一个引用类型,其base是foo对象,在函数bar激活时用作this。

但是,用另外一种形式激活相同的函数,我们得到其它的this值。

因为test作为标示符,生成了引用类型的其他值,其base(全局对象)用作this 值。var testReference = { base: global, propertyName: 'test'}; 现在,我们可以很明确的告诉你,为什么用表达式的不同形式激活同一个函数会不同的this值,答案在于引用类型(type Reference)不同的中间值。

另外一个通过调用方式动态确定this值的经典例子:

函数调用和非引用类型

因此,正如我们已经指出,当调用括号的左边不是引用类型而是其它类型,这个值自动设置为null,结果为全局对象。让我们再思考这种表达式:

在这个例子中,我们有一个函数对象但不是引用类型的对象(它不是标示符,也不是属性访问器),相应地,this值最终设为全局对象。

更多复杂的例子:

为什么我们有一个属性访问器,它的中间值应该为引用类型的值,在某些调用中我们得到的this值不是base对象,而是global对象?

问题在于后面的三个调用,在应用一定的运算操作之后,在调用括号的左边的值不在是引用类型。

1.第一个例子很明显———明显的引用类型,结果是,this为base对象,即foo。

2.在第二个例子中,组运算符并不适用,想想上面提到的,从引用类型中获得一个对象真正的值的方法,如GetValue。相应的,在组运算的返回中———我们得到仍是一个引用类型。这就是this值为什么再次设为base对象,即foo。

3.第三个例子中,与组运算符不同,赋值运算符调用了GetValue方法。返回的结果是函数对象(但不是引用类型),这意味着this设为null,结果是global对象。

4.第四个和第五个也是一样——逗号运算符和逻辑运算符(OR)调用了GetValue 方法,相应地,我们失去了引用而得到了函数。并再次设为global。

引用类型和this为null

有一种情况是这样的:当调用表达式限定了call括号左边的引用类型的值, 尽管this被设定为null,但结果被隐式转化成global。当引用类型值的base对象是被活动对象时,这种情况就会出现。下面的实例中,内部函数被父函数调用,此时我们就能够看到上面说的那种特殊情况。正如我们在第章知道的一样,局部变量、内部函数、形式参数储存在给定函数的激活对象中。

活动对象总是作为this返回,值为null——(即伪代码的AO.bar()相当于null.bar())。这里我们再次回到上面描述的例子,this设置为全局对象。

有一种情况除外:如果with对象包含一个函数名属性,在with语句的内部块中调用函数。With语句添加到该对象作用域的最前端,即在活动对象的前面。相应地,也就有了引用类型(通过标示符或属性访问器), 其base对象不再是活动对象,而是with语句的对象。顺便提一句,它不仅与内部函数相关,也与全局函数相关,因为with对象比作用域链里的最前端的对象(全局对象或一个活动对象)还要靠前。

同样的情况出现在catch语句的实际参数中函数调用:在这种情况下,catch对象添加到作用域的最前端,即在活动对象或全局对象的前面。但是,这个特定的行为被确认为ECMA--3的一个bug,这个在新版的ECMA--5中修复了。这样,在特定的活动对象中,this指向全局对象。而不是catch对象。

同样的情况出现在命名函数(函数的更对细节参考第章Functions)的递归调用中。在函数的第一次调用中,base对象是父活动对象(或全局对象),在递归调用中,base对象应该是存储着函数表达式可选名称的特定对象。但是,在这种情况下,this总是指向全局对象。

作为构造器调用的函数中的this

还有一个与this值相关的情况是在函数的上下文中,这是一个构造函数的调用。

在这个例子中,new运算符调用“A”函数的内部的[[Construct]] 方法,接着,在对象创建后,调用内部的[[Call]] 方法。 所有相同的函数“A”都将this的值设置为新创建的对象。

函数调用中手动设置this

在函数原型中定义的两个方法(因此所有的函数都可以访问它)允许去手动设置函数调用的this值。它们是.apply和.call方法。他们用接受的第一个参数作为this值,this 在调用的作用域中使用。这两个方法的区别很小,对于.apply,第二个参数必须是数组(或者是类似数组的对象,如arguments,反过来,.call能接受任何参数。两个方法必须的参数是第一个——this。

例如:

结论

在这篇文章中,我们讨论了ECMAScript中this关键字的特征(对比于C++ 和 Java,它们的确是特色)。我希望这篇文章有助于你准确的理解ECMAScript中this关键字如何工作。同样,我很乐意在评论中回到你的问题。

Javascript原型链的原理详解 本文实例分析了Javascript原型链的原理。分享给大家供大家参考,具体如下:一、JavaScript原型链ECMAScript中描述了原型链的概念,并将原型链作为实现继

javascript实现简单的全选和反选功能 本文实例讲解了javascript实现简单的全选和反选功能的详细代码,分享给大家供大家参考,具体内容如下效果图:具体代码:!DOCTYPEhtmlhtmllang="en"headmetachar

JavaScript实现简单的tab选项卡切换 本文实例讲解了JavaScript实现简单的tab选项卡切换的示例代码,分享给大家供大家参考,具体内容如下效果图:具体代码:!DOCTYPEhtmlhtmllang="en"headmetacharset

标签: javascrip语言

本文链接地址:https://www.jiuchutong.com/biancheng/384715.html 转载请保留说明!

上一篇:基于javascript实现图片懒加载(用javascript)

下一篇:Javascript原型链的原理详解(javascript原型链详解)

  • 小规模纳税人执行小企业会计准则吗
  • 耕地占用税税率变化历程
  • 结转增值税会计摘要
  • 车辆购置税计算器公式
  • 认缴制的注册资本实缴时存哪里
  • 何谓运输,交通和交通运输
  • 建筑公司预收了款项已经开了增值税发票怎么做账
  • 公司户和个人户卖车的时候价格差多少
  • 子公司借钱给母公司的会计处理
  • 汇算清缴现金流量表怎么填
  • 个人所得税B表和C表
  • 无形资产减值损失一经确认在以后期间不得转回
  • 建筑企业异地预交税款如何处理
  • 视同销售不开票如何计算增值税?
  • 供应商发出货物,将发货单提交给
  • 结转损益主营业务成本在借方还是贷方
  • 实收资本变更做账依据
  • 电商平台流量费用怎么算
  • 加工原因造成的废品损失
  • 医药酒精现在要兑水喝吗
  • 扣除工资作为违约金
  • 专票开票出框可以改吗
  • 小规模没有进项票可以开销项票吗
  • 递延所得税费用影响净利润吗
  • 专家评审费个人所得税计算公式
  • 防暑降温需要缴什么费用
  • 税务稽查的四个环节
  • 固定资产一次性扣除政策2023文件
  • 支付短期借款利息
  • 所得税工资薪金允许税前扣除
  • 小规模纳税人的认定标准是什么
  • mac怎么还原出厂设置
  • 职工教育经费的扣除限额
  • 购入的财务软件怎么入账
  • 企业社保参保人数查询
  • php tr td
  • 切换到多任务界面
  • vue做移动端
  • pqhelper.exe是什么进程 pqhelper进程查询
  • 今天端午节是几月几号啊
  • 小企业会计准则财务报表至少包括
  • 公允价值变动损益在利润表哪里
  • 什么是市盈率和市净率,谈谈你对两个指标的理解
  • 微信支付开发文档教程
  • 长期应付款核算范围有哪些
  • php_curl.dll
  • php destruct
  • 计提本月银行存款应收利息会计分录
  • webpack怎么优化
  • sqlsever修改数据
  • 出租营改增之前取得的有形动产
  • 食堂购买固定资产会计处理
  • sql怎么用sql语句创建表
  • 企业筹建期间可以上市吗
  • 生产型企业出口退税计算
  • 车间劳务费计入什么费用
  • 发票已开后 对方公司名称变更怎么处理?
  • 记账凭证如何填写明细科目
  • mysql如何解压
  • mysql的密码忘了该怎么办
  • 组策略 guest
  • 进程lsass.exe
  • 轻松搞定琥珀甲教程
  • linux三种用户权限
  • 平板电脑安装的是什么格式的软件
  • win10系统打开cad出现致命错误
  • javascript对象的属性和方法
  • 安卓用什么抓包
  • nodeJS(express4.x)+vue(vue-cli)构建前后端分离实例(带跨域)
  • Unity KillCount
  • java urlencode如何使用
  • Android通知栏点击打开安装
  • python函数的方法
  • jquery教程
  • python函数判断质数
  • comparable接口怎么用
  • 税票上的开票员是谁
  • 电子税务局季度利润表本月数
  • 广西税务局客服电话时间
  • 多张发票怎么粘贴在a4纸上面
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设