Javascript浅谈之引用类型


Posted in Javascript onDecember 18, 2013

简介
1.引用类型(Reference type)
引用类型是javascript中一种内部类型。它主要是当做一个指代,代替一个变量或者函数,当然在需要真实值时,又可以通过它寻找到真实值。

2.引用类型的结构
引用类型的值时由两部分构成,一是引用类型的值指代的对象的所属对象,这里我们姑且把它叫做base,二是base中的指代对象的对象名称。用伪代码来表示:

var valueOfReferenceType = {
base: <base object>,
propertyName: <property name>
};

3.使用情景
引用类型的使用情景有二:

(1)在处理一个标示符时

标示符是变量名,函数名,函数参数名和全局对象中未识别的属性名。

(2)在处理一个属性访问器时

var foo = 10;
function bar( ){}

在操作的中间结果中,引用类型对应

var fooReference = {
        base: global,
        propertyName: 'foo'
    };    var barReference = {
        base: global,
        propertyName: 'bar'
    };

这里还是有必要解释一下base,在javascript中所有对象或者函数都有所属对象,看过我前面文章的人都知道,在每个执行上下文有个变量对象专门来管理这个执行上下文中的变量或者函数。

所以,当处理标示符时:

在全局上下文中,毋庸置疑,base === globalVO === gloabal

在函数的执行上下文中,base === VO/AO

但处理对象属性是:

这个更是简单,base === owerObject

4.获取引用类型的真正值
一开始我们说了,引用类型只是一个指代,而不是它并不保存真正的值。当需要真正的值时,可以通过内部一系列算法,可以得到。这个算法,我们可以用简单的伪代码来描述:

function GetValue(value) {  if (Type(value) != Reference) {
    return value;
  }
  var base = GetBase(value);
  if (base === null) {
    throw new ReferenceError;
  }
  return base.[[Get]](GetPropertyName(value));
}

内部的[[Get]]方法返回对象属性真正的值,包括对原型链中继承的属性分析。所有通过GetValue我们也可以轻松获取引用类型的真正的值。如下例:

GetValue(fooReference); // 10
GetValue(barReference); // function object "bar"

那我们什么时候需要获取引用类型的真正值呢?

一般是在引用类型需要进行赋值、参与运算或者被调用是需要通过GetValue方法获取真正值。(注意:通过GetValue获取到的对象不再是引用类型)

引用类型与this的关系
引用类型主要是跟函数上下文中的this指向关系密切,且不同时候看起来还差异挺大,所有我们才引出引用类型来专门解释函数上下文中this的表现。

函数上下文中确定this值的通用规则如下:

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

下面我们根据调用括号左边不同分三种情况进行讨论:

(1)调用括号左边是引用类型的值

这无需作过多分析,base对象就是this值,找到base即可。如果是全局变量下申明的,那就指向全局对象。

var myObject = {
     foo : function(){
            console.log(this);
      }  
}
myObject.foo(); //毫无疑问,这个foo的base是myObject,故foo方法中的this指向myObject。

(2)调用括号左边是引用类型的值,不过这个值为null

function myFunction() {
     var foo = function(){
            console.log(this);
      }  
       foo();    //AO.foo() => null.foo()
}
myFunction(); //输出:Window {top: Window, window: Window...}

当一个内部函数被调用时,这个内部函数的base应该是当前执行上下文中活动对象(OA),但是在javascript内部在OA作为base时,都当做null处理,javascript当然不允许this为null的情况发生,所有就将base设置为global对象(这是前文this函数调用模式中设计错误的源头)。所以在这情况下,this都指向全局对象。

(3)调用括号左边不是引用类型的值

//简单点的例子
(function () {
  console.log(this); // null => global
})();
//复杂些的例子
var foo = {
  bar: function () {
    console.log(this);
  }
};
foo.bar(); // Reference, OK => foo
(foo.bar)(); // Reference, OK => foo
(foo.bar = foo.bar)(); // global
(false || foo.bar)(); // global
(foo.bar, foo.bar)(); // global

当调用括号的左边不是引用类型而是其它类型,this自动设置为null,结果为全局对象。

第一个例子中,立即函数,它的函数调用小括号左边是一个表达式,不是一个引用。

第二个例子复杂了许多,我们来一个个分析:

foo.bar(),这个没有疑问,base为foo,this指向foo。

(foo.bar)(),这里用到了一个小括号,它在这起到分组符作用,也就是它不会迫使引用类型执行GetValue方法,其执行结果,跟上面一模一样。

后面三个,小括号里面依次是赋值运算、或运算和逗号运算,它们都会迫使引用类型执行GetValue方法,从而返回一个函数对象。这样,函数调用小括号左边就不再是引用类型了,所有,this都是指向全局对象的。

总结

关于引用类型,其实我都一直不太了解这个,只是看到汤姆大叔的博客中this那章,为了解释函数调用模式中this的取值原理且专门分析了一下,这一分析可不得了,我之前一直认为引用类型和引用传值应该存在某些关系,没想到,它大叔bolg中只是用来辅助理解this。至于他们二者之前有没有关系,如果有关系到底是一种什么关系,这还得我继续学习研究。

希望大家多交流。在此还是的感谢汤姆大叔.

Javascript 相关文章推荐
锋利的jQuery 要点归纳(一) jQuery选择器
Mar 21 Javascript
基于jquery实现的文字向上跑动类似跑马灯的效果
Jun 17 Javascript
14个有用的Jquery技巧分享
Jan 08 Javascript
每天一篇javascript学习小结(基础知识)
Nov 10 Javascript
微信小程序 swiper组件详解及实例代码
Oct 25 Javascript
js模糊查询实例分享
Dec 26 Javascript
Node.js Express 框架 POST方法详解
Jan 23 Javascript
react-native ListView下拉刷新上拉加载实现代码
Aug 03 Javascript
element-ui 设置菜单栏展开的方法
Aug 22 Javascript
微信小程序实现下拉菜单切换效果
Mar 30 Javascript
使用NestJS开发Node.js应用的方法
Dec 03 Javascript
微信小程序实现动态列表项的顺序加载动画
Jul 25 Javascript
浅析JQuery UI Dialog的样式设置问题
Dec 18 #Javascript
Jquery ajaxStart()与ajaxStop()方法(实例讲解)
Dec 18 #Javascript
jQuery.event兼容各浏览器的event详细解析
Dec 18 #Javascript
jquery中event对象属性与方法小结
Dec 18 #Javascript
深入理解jQuery中live与bind方法的区别
Dec 18 #Javascript
解析JSON对象与字符串之间的相互转换
Dec 18 #Javascript
cookie中的path与domain属性详解
Dec 18 #Javascript
You might like
浅析使用Turck-mmcache编译来加速、优化PHP代码
2013/06/20 PHP
php的SimpleXML方法读写XML接口文件实例解析
2014/06/16 PHP
PHP连接sql server 2005环境配置及问题解决
2014/08/08 PHP
会自动逐行上升的文本框
2006/06/30 Javascript
用Javascript实现锚点(Anchor)间平滑跳转
2009/09/08 Javascript
原生Js与jquery的多组处理, 仅展开一个区块的折叠效果
2011/01/09 Javascript
jqgrid 简单学习笔记
2011/05/03 Javascript
javascript延时加载之defer测试
2012/12/28 Javascript
ExtJS4 Grid改变单元格背景颜色及Column render学习
2013/02/06 Javascript
Jquery实现自定义窗口随意的拖拽
2014/03/12 Javascript
jQuery操作JSON的CRUD用法实例
2015/02/25 Javascript
jQuery焦点图切换特效代码分享
2015/09/15 Javascript
JS实现消息来时让网页标题闪动效果的方法
2016/04/20 Javascript
基于jQuery和Bootstrap框架实现仿知乎前端动态列表效果
2016/11/09 Javascript
js限制input只能输入有效的数字(第一个不能是小数点)
2018/09/28 Javascript
原生JS实现随机点名项目的实例代码
2019/04/30 Javascript
vue 组件开发原理与实现方法详解
2019/11/29 Javascript
小程序实现简单语音聊天的示例代码
2020/07/24 Javascript
JavaScript Html实现移动端红包雨功能页面
2021/01/10 Javascript
vue 使用饿了么UI仿写teambition的筛选功能
2021/03/01 Vue.js
python动态加载包的方法小结
2016/04/18 Python
python实现逆序输出一个数字的示例讲解
2018/06/25 Python
python中reader的next用法
2018/07/24 Python
利用Pycharm断点调试Python程序的方法
2018/11/29 Python
Python OpenCV利用笔记本摄像头实现人脸检测
2020/08/20 Python
Django CBV模型源码运行流程详解
2020/08/17 Python
使用 CSS3 中@media 实现网页自适应的示例代码
2020/03/24 HTML / CSS
BOSE德国官网:尽探索之力,享音乐之极
2016/12/11 全球购物
新加坡第一大健康与美容零售商:屈臣氏新加坡(Watsons Singapore)
2020/12/11 全球购物
会计系毕业个人自荐信格式
2013/09/23 职场文书
初中优秀学生评语
2014/12/29 职场文书
税务会计岗位职责
2015/04/02 职场文书
关于远足的感想
2015/08/10 职场文书
2016感恩父亲节主题广播稿
2015/12/18 职场文书
一封真诚的自荐信帮你赢得机会
2019/05/07 职场文书
导游词范文之颐和园/重庆/云台山
2019/09/10 职场文书