现在的位置: 首页 > 综合 > 正文

JavaScript数据类型

2018年02月19日 ⁄ 综合 ⁄ 共 6092字 ⁄ 字号 评论关闭
文章目录

JavaScript数据类型

          本文假设读者已经学习过类C/C++这样的编程语言,从这篇文章开始,博主讲以一个C/C++程序员的视角来学习JavaScript编程语言。学习一门新的编程语言,无非就是学习语法的以下属性:(1)基本数据类型,变量及扩展数据类型;(2)函数;(3)对象及其继承多态等机制。今天就让我们看看JavaScript数据类型与C/C++有和不同。

 

 

一、基本数据类型

1、 简单数据类型

          数字(number),字符串(string),布尔值(boolean),Null,Undefinded。前三种都不是对象。但是Js中提供了将他们包装成对象的方法(构造器)。他们也称为原生数据类型。

2、复杂数据类型

         数组,对象,函数属于复杂数据类型,对于数组我们不做过多介绍,我们只要知道它是一种特殊对象就可以了。这里我们需 要仔细探讨的是对象和函数。实际上在Js中函数也是对象。但是对象不一定是对象。只有函数对象才是函数,一般由内置构造器Function或者关键字function来声明。

(1)Function与Object

           FunctionObject是所有函数和所有对象的根构造器。在Js中类型和构造器是直接关联的,在Js中构造器充当C/C++中类的角色。且构造器本身是一个函数对象。也许刚从类C++语言阵营转向Js的朋友们感觉这非常困惑。其实不然,我们

       只需要跳出以类为模板的对象构造的定式思维。先看一个例子:          

var function_name = new Function(arg1,arg2, ..., argN, function_body)

          对于声明函数我们看个例子:               

//函数声明1
//add全局,但是在之前属于未定义状态,不可调用
var add = new Function(x,y,"return x+y;")
//函数声明2
//add1同add
var add1 = function(x,y){return x+y;};
//函数声明3
//全局可调用
function  add3(x,y)
{
        return x+y;
}

          三种方法产生的函数对象都是Function(类似类的构造器)的实例。也许你会困惑,Function本身是对象,他如何能够构造其他对象呢,其实这一点也不起怪,想想你自己。你是你爸妈生的,但是你爸妈也是一个人,他们并不是一个虚幻的类。至于你要追根溯源,想找出你的根祖先就有点难以理解,其实Js中大抵如此。博主也有一点没有特别清晰:既然函数也是对象,而对象又需要构造器(函数)来构造,那么是谁生成了构造函数的根构造器呢?那么是先有函数还是先有对象呢?也就是Object是否由Function构造?粗浅的理解:Js中有一个元祖先----Object.prototype------它是万物之源,所有对象都默认直接或间接继承自它。也就是说FunctionObject都具有该属性对象。事实上Object应该是Function的一个实例。因为所有函数都来自与Function,而对象的构造器是函数,所以对象的根构造器Object同样来自于FunctionFunction自己则来自于自己(也就是自举性)。不过ObjectFunction等内建对象构造器是Js解释引擎内部实现的。可能实现的具体细节有差异,但语义应该都是一样的。

(2)函数

          在Js中函数有一个根构造器Function(对象),它是一个特别的函数,是一个极其特别的对象,因为其他构造器都是用构造普通对象的,但是Function是用来构造

       构造器的(函数),所以为区分这个特殊构造器和普通构造器,我们可以将Function称为元构造器。它不可以作为普通函数来调用。

       构造器:每一个函数都有两个作用,(1)普通函数;(2)构造器----使用new关键字调用时(当函数有return语句时,会把构造产生的对象丢掉,返回return返回的结果);

      构造器分类:(1)元构造器Function)-----用于生成普通构造器;(2)普通构造器------用于产生非函数对象;

      函数的两个重要属性:(1)函数对象所属原型{Prototype}-----__proto__;   (2)作为构造器时,构造出来的普通对象的原型prototype;(__proto__属于对象,而prototype属于构造器用于构造对象时作为原型,这样的话函数对象的__proto__属性是构造他的构造器的prototype的一个引用。prototype类似于模板的作用,用于构造对象时作为图纸,而__proto__用于对象查询自己来自哪个模板,或者说共享了哪个原型对象,也是用于查询原型链的中介,或者说是原型链的节点)。

      
由于Js是动态语言,所以可以随时给构造器或构造器的prototype(原型对象)添加新的方法和属性。本来想到下一篇文
章才会讲到继承的,但是这里先提一点,Js中所谓的原型继承,其实只是共享一个prototype对象来实现。严格来讲这并非严格意义的继承,prototype并没有真正被子对象继承。prototype只是由构造器维护,而子对象只是通过设obj.__proto__=
ConstructFuc.prototype。对象只是维护原型对象的一个引用。并没有真正拥有它,它类似于C/C++中类中的静态成员,
属于类,所有类的对象共有。例如:

                      

(3)对象

            在Js中对象由构造器产生(var object ={code block;}形式调用同样调用了构造器Object),对象由以下结构组成:

       (1)一个{Prototype}属性,在IE中不可直接访问,但是提供了方法访问。但是firefox等提供了一个__proto__属性。用于原型机制。默认情况下,对象的原型为自身(__proto__ = this)。

      (2)构造器中定义的数据结构(属性+方法)。)对象自身的数据结构(方法+属性);

            (3)  构造器行为:(a)根据构造器中的属性和方法构造对象;(b)将该对象的原型__proto__设置为自身;(c)返回生成的对象。

 

3、原始类型和引用类型

          Js中变量分为原始类型引用类型。数值,布尔值,null和未定义的值属于原始类型,对象,数组和函数属于引用类型。

       原始类型:赋值是值传递,且内存大小固定;

       引用类型:赋值是传递引用,且内存大小可变;

       从更深层次来讲,声明一个变量var variable;如果赋值一个原始类型的数据给它,那么该变量所对应的内存存储的就是实实在在地数据。而如果给他赋值一个引用类型的数据,那么是将该数据的存放地址放入变量中,这样取数据其实是间接寻址。

       有一个比较特殊的类型----字符串,在《JavaScript权威指南》中也没说明白它到底属于哪一种类型。这里就不深究。

 

二、数据类型实现模型

Build-in *** data structure: 指JS内部用于实现***类型的数据结构,这些结构我们基本上无法直接操作。
Build-in *** object:指JS内置的Number, String, Boolean等这些对象,这是JS将内部实现的数据类型暴露给开发者使用的接口。
Build-in *** constructor:指JS内置的一些构造器,用来构造相应类型的对象实例。它们被包装成函数对象暴露出来。

 

三、对象模型

1. 图中有好几个地方提到build-in Function constructor,这是同一个对象,可以测试验证:

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
Function==Function.constructor //result: true
Function==Function.prototype.constructor //result: true
Function==Object.constructor //result: true
//Function also equals to Number.constructor, String.constructor, Array.constructor, RegExp.constructor, etc.
function fn(){}
Function==fn.constructor //result: true

这说明了几个问题: Function指向系统内置的函数构造器(build-in Function constructor);Function具有自举性;系统中所有函数都是由Function构造。

2. 左下角:的obj1, obj2...objn范指用类似这样的代码创建的对象:

function fn1(){};

var obj1=new fn1();

这些对象没有本地constructor方法,但它们将从Prototype链上得到一个继承的constructor方法,即fn.prototype.constructor,从函数对象的构造过程可以知道,它就是fn本身了。

右下角:的obj1, obj2...objn范指用类似这样的代码创建的对象:

 var obj1=new Object();

或var obj1={};

或var obj1=newNumber(123);

或obj1=/\w+/;

等等。所以这些对象Prototype链的指向、从Prototype链继承而来的constructor的值(指它们的constructor是build-in Number constructor还是build-in Object constructor等)等依赖于具体的对象类型。另外注意的是,var obj=new Object(123);这样创建的对象,它的类型仍然是Number,即同样需要根据参数值的类型来确定。同样它们也没有本地constructor,而是从Prototype链上获得继承的constructor方法,即build-in
*** constructor,具体是哪一个由数据类型确定。

3. 关于图中Prototype链的补充说明:
Object.prototype是整个链的终结点,它的内部[[Prototype]]为null。
所有函数的Prototype链都指向Function.prototype。
Function的Prototype链指向Function.prototype,这是规范要求的,因为设计者将Function设计为具有自举性。Function的Prototype链这样设计之后,Function.constructor==Function, Function instanceOf Function都为true。另外Function已经是最顶层的构造器,但Function本身也是一个函数对象,它必然是由某个东西创建出来的,这样自举在语义上合情合理。Function.prototype的Prototype链指向Object.prototype,这也是规范强制要求的。首先Function.prototype是Function的一个实例对象(typeof
Function.prototype可以知道它是一个Function,instanceOf无法通过测试,因为Prototype链在内部被额外设置了),所以按照Prototype的规则,Function.prototype的内部[[Prototype]]值应当为Function.prototype这个对象,即它的Prototype链指向自己本身。这样一方面在Prototype链上造成一个死循环,另一方面它本身成为了一个终结点,结果就是所有函数对象将不是派生自Object了。加上这个强制要求之后,Prototype链只有唯一的一个终结点。

4. 因为Function.prototype是一个函数对象,所以它应当具有显示的prototype属性,即Function.prototype.prototype,但只有FireFox中可以访问到,IE、Opera、Safari都无法访问。所以图中用了个表示不存在的符号。

5. 用户自定义函数(user defined functions)默认情况下[[Prototype]]值是Object.prototype,即它的隐式Prototype链指向Object.prototype,所以图中就这样表示了,但并不代表总是这样,当用户设置了自定义函数的prototype属性之后,情况就不同了。

下一篇我们将讨论JavaScript的原型继承机制:JavaScript原型继承机制

 

 

最后再声明一下,任何添加属性和方法的操作都是向对象添加属性和方法。

引用:

声明函数的方法:

http://www.360doc.com/content/09/0703/15/16915_4124895.shtml

对象模型:

http://www.cnblogs.com/RicCC/archive/2008/02/15/JavaScript-Object-Model-Execution-Model.html(强烈推荐)

 http://zeekat.nl/articles/constructors-considered-mildly-confusing.html#fn.1

https://developer.mozilla.org/zh-CN/docs/JavaScript/Guide/Details_of_the_Object_Model

函数对象与函数名的区别:

http://www.cnblogs.com/ArthurPatten/p/3297992.html

javascript函数声明、函数表达式和函数构造器:

http://openwares.net/js/javascript_function.html

this指针:

http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html(阮一峰博客,强烈推荐)

理解javascript原型:

http://blog.jobbole.com/9648/

 

构造器行为:

http://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript

http://zeekat.nl/articles/constructors-considered-mildly-confusing.html

 

 

抱歉!评论已关闭.