1.简单数据类型

  在JavaScript中简单数据类型分为5种。分别为 Undefined, Null,Boolean,Number,String.

  • Undefined类型
    Undefined类型只有一个值,即特殊的undefined。在使用var对变量声明的时候,变量的值即被初始化为undefined.
    在使用typeof求得数据类型的时候,对于未声明的变量返回的总是undefined.
  • Null类型
    Null也只有一个值得数据类型,其实质是一个指向空对象的指针。所以使用typeof操作的时候返回的是一个object类型。
    var object = null;
    console.log(typeof object);//object

    实际上,Undefined派生自Null类型。所以,Ecma-262规范中,null==undefined //值为true.

  • Boolean类型
    Boolean类型只有两个值ture或者false.
  • Number类型
    Number数据类型有几个比较常使用的数值常量。
      
      (1)最大值: Number.MAX_VALUE.
      (2)最小值: NUMBER.MIN_VALUE.
        (3)正无穷大: Infinity
      (4)负无穷大: -Infinity
        (5)非数字   :NaN.

    数值转换:
    数值转换有三种常见的函数:Number, ParseInt, ParseFloat
    Number常用于转型函数,而后两种常用于字符串转数值。

  • String类型
    基本数据类型中,最复杂的一种也就是字符串了。

      字符串的特点:
      (1).单双引号报过都可。
      (2).字符串不可变。
         什么是字符串不可变?      

 var str1="hello";  //开辟一份新空间
var str2="world"; //开辟一份新空间
str1=str1+str2;  //因为字符串的不可变特性,改变字符串会重新开辟一份新空间,以前的那一份在一段时间后被垃圾回收机制回收。
console.log(str1);         作为基本数据类型,字符串作为函数参数的时候是传值还是传引用呢?

    如果传值:   则必须复制一份新的字符串作为参数。字符串如果太长的话,很明显,浪费空间。
    如果传引用: 字符串作为参数,如果值没有改变,则不需要开辟新的空间。
           如果值改变,又因为字符串不可变的特性而会重新开辟新的空间。
           所以,字符串在作为参数的时候是传引用而非传值。

注: 关于传值还是传引用,我们这里参照物均为变量本身。------详情请看第三部分。

2.复杂数据类型  

  复杂数据类型也就是我们常说的引用类型.引用类型是一种数据结构,其值也就是其所指向的对象。
  ECMAScript提供了很多原生态的引用类型。

  • Object类型
        (1)两种创建方式
    • //第一种,使用构造函数。
      var object=new Object();
      object.name="xxxx"; //第二种,使用字面量的创建方式,程序员更倾向于第二种
      var object={
      name:"xxxx"
      }

(2) 对象的属性


Object数据类型的对象是采用松散的结构组织属性的。所谓的松散,就是我们所说的用键值对来保存对象。而键值对以hash表结构存储。

有关于对象以键值对存储的文章,详情见对象基于哈希存储(<Key,Value>之Key篇(1)

     Object类型的对象,属性可以分为两类:

      a.数据属性

        数据属性有四个描素其行为的特性。  

      1. [Configurable]:表示是否可以通过delete删除该属性,能否修改属性的特性。

        var object = {
        name: '张三'
        };
        Object.defineProperty(object, 'name', {
        configurable: false
        });
        delete object.name; //false

        Object.defineProperty(object, 'name', {
        configurable: true
        });    //error:TypeError: can't redefine non-configurable property 'name'

      2. [Enumerale]:表示该属性是否可以通过for-in循环遍历
        var object = {
        name: '张三',
        age:18
        };
        Object.defineProperty(object, 'name', {
        configurable: false,
        enumerable: false
        });
        for (var property in object) {
        console.log(property); //age
        }
      3. [Writable]:表示该属性的值是否能被更改
        var object = {
        name: '张三',
        age:
        };
        Object.defineProperty(object, 'name', {
        configurable: false,
        enumerable: false,
        writable: false
        });
        object.name = '李四';
        console.log(object.name);//张三,name未被更改
      4. [Value]:保存属性的值,写入属性的时候,将属性的值保存在此位置;读取此属性的时候,从该值中读取。
        var object = {
        name: '张三'
        };
        Object.defineProperty(object, 'age', {
        configurable: false,
        enumerable: false,
        writable: false,
        value:
        });
        console.log(object.age);//         
          

b.访问器属性:访问器属性不包含数据值,但其包含getter和setter函数。其也有四个特征值对其进行描述

      1. [Configurable]:表示是否可以通过delete删除该属性,能否修改属性的特性。
      2. [Enumerale]:表示该属性是否可以通过for-in循环遍历。
      3. [Get]:在读取属性时,调用的函数。
        var object = {
        name: '张三',
        age:
        };
        Object.defineProperty(object, 'isAdult', {
        configurable: false,
        enumerable: false,
        get: function () {
        if (this.age < ) {
        return false;
        } else {
        return true;
        }
        }
        });
        console.log(object.isAdult);//true isAdult就是一个访问器属性
      4. [Set]:在写入属性时调用的函数
        var object = {
        name: '张三',
        age:
        };
        Object.defineProperty(object, 'changeAge', {
        configurable: false,
        enumerable: false,
        set: function (value) {
        this.age = value;
        }
        });
        object.changeAge=;
        console.log(object.age);//

  (3)对象的常用方法

    •  toString():返回对象的字符串形式。
    •  valuOf():该方法取得对象的基本数据类型。一般返回的是个数值。 其与toString()方法的区别,详请见JavaScript系列-----对象基于哈希存储(<Key,Value>之Value篇) (3)
    •  hasOwnProperty(attrName):判断对象中是否有某一个属性,且该属性不在对象的原型对象上。
    •  Object.getOwnPropertyNames(object):返回一个数组,数组中保存着对象object中的所有属性名,且该属性不在原型对象上。  

  • Array类型
    (1)定义:数组对象用来在单独的变量名中存储一系列的值。
    (2)创建方式:
    //第一种 使用构造函数
    var mycars=new Array()
    mycars[0]="Saab"
    mycars[1]="Volvo"
    mycars[2]="BMW"
    或者 var mycars=new Array("Saab","Volvo","BMW") //第二种 使用数组字面量
    var colors=["red","blue","green"]; 

    (3)数组的属性
      
    length:数组的 length 属性总是比数组中定义的最后一个元素的下标大 1,通过length 属性可设置或返回数组中元素的数目。

    var array=[];
    array[100]=10;
    console.log(array.length);//101

    array=[1,2,3,4,5];
    array.length=3;
    console.log(array);//1,2,3

  • Date类型

    创建方式:

    • var myDate=new Date(); //Date 对象自动使用当前的日期和时间作为其初始值。

       补充说明:对于时间  其月份总是从0开始算起,即月份表示 0---11.而其他的和我们正常所理解的是一致的。

  • 函数类型(参见本系列第四篇函数篇
  • RegExp类型(在下一篇文章中作为专题)

 3.传值和传引用 

      (1)问题的起源

其实这个问题来源于C和C++,因为C或C++里都有一个特殊的数据类型----指针,那时候所谓的传值和传引用是对指针来说的。
那么针对指针来说,什么是传值,又什么是传引用呢?首先,指针作为一种数据类型,其本身肯定是占用一定的内存空间,而且,指针同时还要指向另一块内存空间。

      如图所示:

针对指针来说,指针作为一种数据类型,指针的标识符也就是其在内存中所在的地址,指针的值就是其所指向的地址。也就是说,指针值是地址。
那么一个指针在作为函数的参数的时候,传给参数的到底是指针的地址还是指针的值呢? ----这就是传值和传引用问题的起源.

    (2)指针的传值和传引用
            函数的参数,在函数被调用的时候,在其函数所开辟的那个栈中是占用一定的内存空间的,那么这块内存空间的值是什么呢?

首先,先肯定一点,形参的值来源肯定是实参。那么,实参给形参赋值的时候传的是什么呢?

          (1)传的是结构体地址,那么就如图所示:

                

如果传的是结构体的地址,那么也就是指针的值赋值给形参。所以,这就是我们所谓的传值。由图中我们可以看出,如果是传值的话,那么作为形参的指针和作为实参的指针,指向的是同一个结构体。

      
    
 (2)如果传的是指针的地址,那么指针的地址就会赋值给形参。结果,如图所示:
        

  对于传引用来说,形参的值是指针的地址,那么每次对形参的改变,其实改变的都是指针所指向的地址。而如果向取得结构体的地址,也需要通过实参的地址。
    

(3)JS中只存在传值

首先需要明确一写概念,即引用和对象的概念。

引用:也就是我们所说的指针,其存在于栈中。

对象:也就是上图中我们所标记的结构体,其存在于堆中。

引用的值就是对象所在的地址。我们用一个例子说明: 

var person = {
name: '张三',
age: 18
};
function setName(object) {
object.name = '王五';
}
setName(person);
console.log(person.name);//王五

依然用图来解释:

从上图中我们可以看书,函数在传参是,传的是实参的值,也就是指针的值。我们,我们这里理解为传值。

但是,换一种角度来说,把对象当作参照物,传给形参的值就是对象的地址,也并非对象本身,说是传引用也不为过。

所以,无论是传值还是传引用,只要理解了即可。没必要纠结于字眼。

(4)基本数据类型传值

首先基本数据类型与引用数据类型相比的差别就是,基本数据类型保存在函数运行时的栈中,而引用数据类型的值保存在堆空间中。那么,如果基本数据类型给形参赋值的时候是怎样的呢?

举个例子:

var x = 1;
function add(num) {
return num + 1;
}
add(1);

x作为实参,num作为函数的形参,当函数add被调用时,形参num被赋值为实参x的值。即 num=1;结构图如下所示:

如上如所示,此时对形参的值做任何改变均与实参无关,实参和形参是两个互不关联的个体。

补充一点: 字符串也是一种数据类型,那么字符串的值保存在哪里呢? 其作为函数参数的时候,传值是如何进行的呢?

字符串虽然也是一种基本数据类型,但因为其大小不固定,所以,其一般其更像与引用数据类型。但其又有其特殊性----不可变性。

  什么是字符串的不可变?

var str="";
for(var i=0;i<3;i++){
str+=i;
}
console.log(str);//012

看上图程序,字符串是可以改变的。那为什么还要说,字符串不可变呢,先别急,我们来分析一下程序运行时内存结构图。

          

         

看到没有,每一次字符串值的改变,其所指向的地址都会跟着改变一次。其所说的不可变,是跟引用数据类型相比来说,引用数据类型值的改变一般是对象本身的改变,而其指向是不变的,而字符串值的改变是其指向地址的改变。所以,字符串的每一次改变都会产生垃圾,此垃圾过一段时间会被垃圾回收机制回收。

了解了上述的情况,所以字符传在作为参数的时候,为了节省空间,只是复制了字符串所指向的地址给形参,而形参的值如果改变了的话,因为字符串具有不可变特性,所以会重新开辟一份空间给形参。如下

var str = '你是谁?';
function change(str) {
str = '我就是我了';
}
change(str);
console.log(str);//你是谁

  

字符串在Java C++中均作为比较特殊的一种类型,JS中虽然将其当作一种基本数据类型,但是其使用时更偏向于引用数据类型,但是其又具有不可变型,才促使我们可以将其当作基本数据类型使用。

JavaScript系列----数据类型以及传值和传引用的更多相关文章

  1. java中的传值与传引用

    java函数中的传值和传引用问题一直是个比较“邪门”的问题,其实java函数中的参数都是传递值的,所不同的是对于基本数据类型传递的是参数的一份拷贝,对于类类型传递的是该类参数的引用的拷贝,当在函数体中 ...

  2. java 函数形参传值和传引用的区别

    java方法中传值和传引用的问题是个基本问题,但是也有很多人一时弄不清. (一)基本数据类型:传值,方法不会改变实参的值. public class TestFun { public static v ...

  3. C++传值、传引用

    C++传值.传引用 C++的函数参数传递方式,可以是传值方式,也可以是传引用方式.传值的本质是:形参是实参的一份复制.传引用的本质是:形参和实参是同一个东西. 传值和传引用,对大多数常见类型都是适用的 ...

  4. 【转载】Java是传值还是传引用

    1. 简单类型是按值传递的 Java 方法的参数是简单类型的时候,是按值传递的 (pass by value).这一点我们可以通过一个简单的例子来说明: /* 例 1 */ /** * @(#) Te ...

  5. Java经典问题:传值与传引用?

    转自:http://developer.51cto.com/art/201104/254715.htm Java到底是传值还是传引用?相信很少有人能完全回答正确.通常的说法是:对于基本数据类型(整型. ...

  6. Java中的值传递和地址传递(传值、传引用)

    首先,不要纠结于 Pass By Value 和 Pass By Reference 的字面上的意义,否则很容易陷入所谓的“一切传引用其实本质上是传值”这种并不能解决问题无意义论战中.更何况,要想知道 ...

  7. java集合中的传值和传引用

    在学习java集合过程中发现了传值和传引用的区别: 我们来看下面两句话 ●java集合就像一种容器,我们可以把多个对象(实际上是对象的引用),丢进该容器.(来自疯狂java讲义) ●当使用Iterat ...

  8. Go语言的传值与传引用

    Go语言里的传值与传引用大致与C语言中一致,但有2个特例,map和channel默认传引用,也就是说可以直接修改传入的参数,其他的情况如果不用指针的话,传入的都是参数的副本,在函数中修改不会改变调用者 ...

  9. python函数传参是传值还是传引用?

    首先还是应该科普下函数参数传递机制,传值和传引用是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题.基本的参数传递机制有两种:值传递和引用传 ...

随机推荐

  1. 基于C#的BarCode 39实现

    一.39条码简介 39码是1974年发展出来的条码系统,是一种可供使用者双向扫瞄的分散式条码,也就是说相临两资料码之间,必须包含一个不具任何意义的空白(或细白,其逻辑值为0),且其具有支援文字的能力, ...

  2. poj1006中国剩余定理

    Biorhythms Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 103506   Accepted: 31995 Des ...

  3. 通过JQuery实现Ajax代码

    今天早上遇到了这个问题,结果我写的顺序是惨不忍睹啊,所有现在留个模版以示标准. $(function(){ $.ajax({ url : "Servlet", //传地址 type ...

  4. 网时|ipone8爆冷,我的服务器空欢喜一场

    上周ipone可谓是占尽了风头,从face ID到全面屏,从人脸识别到逆天价格,小编都能预想到上市之后的一片火热了,苹果后台的服务器恐怕都早已做好了准备,加大带宽,稳定运行,确保万无一失. 9月22日 ...

  5. Python实战之IO多路复用select的详细简单练习

    IO多路复用 I/O多路复用指:通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. select   它通过一个select()系统调用来 ...

  6. ZOJ2006 一道很尴尬的string操作题

    ZOJ2006(最小表示法) 题目大意:输出第一个字符串的最小字典序字串的下标! 然后我居然想试一试string的erase的能力,暴力一下,然后20msAC了,尴尬的数据.......... #in ...

  7. flex的三个属性:

    (1)flex-grow:指的是相对于其他的子元素的扩展比率:默认值为0:数字 (2)flex-basis:指的是子元素的具体长度:可以为长度(rem,px,em)也可以为百分比: (3)flex-s ...

  8. 获取报告 Stream转string,利用字符串分割转换成DataTable

    protected void Button1_Click(object sender, EventArgs e) { MemoryStream stream = new MemoryStream(); ...

  9. zookeeper curator使用caches实现各种监听

    1.篇首语 curator是zookeeper的一个高级api开发包.封装了zookeeper众多的recipes,并且实现了一些新的recipes原语,最重要的是基于zookeeper提供的各种机制 ...

  10. ovs2.7 在系统重启后,再次使用时提示数据库无法连接的问题。

    问题现象如下,ovs开始安装后,对ovs的操作是正常的,但是,现在系统重启后,OVS的操作第一条命令就失败,如下: 问题解决方法: 参考  http://blog.csdn.net/xyq54/art ...