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 相关文章推荐
探索Emberjs制作一个简单的Todo应用
Nov 07 Javascript
jQuery 获取浏览器所在的IP地址的小例子
Nov 08 Javascript
用unescape反编码得出汉字示例
Apr 24 Javascript
JQuery遍历DOM节点的方法
Jun 11 Javascript
jQuery实现单击弹出Div层窗口效果(可关闭可拖动)
Sep 19 Javascript
jquery获取复选框的值的简单实例
May 26 Javascript
jQuery 的 ready()的纯js替代方法
Nov 20 Javascript
Vue系列:通过vue-router如何传递参数示例
Jan 16 Javascript
jQuery插件MovingBoxes实现左右滑动中间放大图片效果
Feb 28 Javascript
JQuery中queue方法用法示例
Jan 31 jQuery
js实现3D旋转相册
Aug 02 Javascript
解决vue watch数据的方法被调用了两次的问题
Nov 07 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
thinkphp5.1框架容器与依赖注入实例分析
2019/07/23 PHP
最简单的jQuery程序 入门者学习
2009/07/09 Javascript
Mootools 1.2教程 选项卡效果(Tabs)
2009/09/15 Javascript
jQuery 美元符冲突的解决方法
2010/03/28 Javascript
juery框架写的弹窗效果适合新手
2013/11/27 Javascript
js实现单行文本向上滚动效果实例代码
2013/11/28 Javascript
Nodejs学习笔记之Stream模块
2015/01/13 NodeJs
ECMAScript5(ES5)中bind方法使用小结
2015/05/07 Javascript
js全选按钮的实现方法
2015/11/17 Javascript
JavaScript面向对象之私有静态变量实例分析
2016/01/14 Javascript
基于jQuery倒计时插件实现团购秒杀效果
2016/05/13 Javascript
js实现多图左右切换功能
2016/08/04 Javascript
js实现背景图自适应窗口大小
2017/01/10 Javascript
使用BootStrap实现标签切换原理解析
2017/03/14 Javascript
详解vee-validate的使用个人小结
2017/06/07 Javascript
vue2.0 better-scroll 实现移动端滑动的示例代码
2018/01/25 Javascript
跨域解决之JSONP和CORS的详细介绍
2018/11/21 Javascript
jQuery+PHP+Ajax实现动态数字统计展示功能
2019/12/25 jQuery
JS实现滑动导航效果
2020/01/14 Javascript
vue实现匀速轮播效果
2020/06/29 Javascript
[01:43]倾听DOTA2英雄之声 魅惑魔女国服配音鉴赏
2013/06/06 DOTA
[46:50]Liquid vs Mineski 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
Python类定义和类继承详解
2015/05/08 Python
Python使用Beautiful Soup包编写爬虫时的一些关键点
2016/01/20 Python
利用python程序生成word和PDF文档的方法
2017/02/14 Python
正确理解python中的关键字“with”与上下文管理器
2017/04/21 Python
python连接数据库的方法
2017/10/19 Python
详解python中的生成器、迭代器、闭包、装饰器
2019/08/22 Python
Python协程操作之gevent(yield阻塞,greenlet),协程实现多任务(有规律的交替协作执行)用法详解
2019/10/14 Python
利用Python将多张图片合成视频的实现
2020/11/23 Python
CSS去掉A标签(链接)虚线框的方法
2014/04/01 HTML / CSS
英国豪华家具和经典家居饰品购物网站:OKA
2020/06/05 全球购物
俄罗斯家居用品购物网站:Евродом
2020/11/21 全球购物
Java面试笔试题大全
2016/11/23 面试题
实习生求职自荐信
2014/02/07 职场文书
Vite + React从零开始搭建一个开源组件库
2022/06/25 Javascript