有关JavaScript变量相关问题详解

迷茫
迷茫 原创
2017-03-26 17:02:29 1024浏览

  本文重在探讨JavaScript变量包含的两种不同数据类型的值——基本类型值和引用类型值的区别。在此外稍微带过ECMAScript和JavaScript的关系。

  题为JavaScript变量,但更具体的说应该是ECMAScript变量。

  二十世纪九十年代,Netscape公司和微软公司推出了两个不同版本的JavaScript,不利于JavaScript的开发和使用,促使欧洲计算机制造商协会(ECMA,European Computer Manufacturers Association)着手处理JavaScript的标准化问题,从而完成了著名的 ECMA-262——定义了一种名为ECMAScript的新脚本语言的标准。

  一个完整的JavaScript实现包括ECMAScript,文档对象模型(DOM,Document Object Model),以及浏览器对象模型(BOM,Browser Object Model)。ECMAScript作为JavaScript的核心以及实现的基础,是ECMA-262标准规定的在语法、类型、语句、关键字、保留字、操作符和对象这几个方面内容的语言的描述。

 ECMA-262标准规定的ECMAScript变量是松散类型的,可以用来保存任何类型的数据,所以不同类型初始化变量的操作可以放在一条语句中执行,如下列代码是合法的。

 var message = "hello",  //string     
 age = 20,           //number3     
 found = false;   //boolean 

  用 var 操作符定义的变量将成为定义该变量的作用域中的局部变量,退出该作用域后变量会被立即销毁。例如在函数内定义一个变量,当函数被调用的时候,该变量即被创建,但在函数退出后,该变量将无法再被继续访问。

  ECMAScript中有6种数据类型(也只有6中,ECMAScript不支持任何创建自定义类型的机制)。

  其中基本数据类型包括5种——underfined、null、boolean、number、string,这5种基本数据类型按值访问,其值属于文章开头提到的基本类型值,是简单的数据段,可以操作保存在变量中的实际的值。

  第6种为复杂数据类型——object,本质上是由一组无序的名-值对组成的,属于引用类型值,是保存在内存中的对象。JavaScript不允许直接操作对象的内存空间,在操作对象时实际是在操作对象的引用而不是实际的对象。

  虽然定义变量时不需要规定其为何种数据类型,但基本类型和引用类型的值可以执行的操作还是大相径庭。

  属性的添加

  对于引用类型的值,可以为其属性和方法进行添加、改变和删除,如下列代码:  

var obj = new object();  //创建对象并保存在obj中
obj.name = "Marry";      //添加名为name的属性,赋予字符串值“Marry”
alert(obj.name);         //弹出"Marry"

  如果obj对象不被销毁或者name属性不被删除,这个属性将一直存在。  

  再看基本类型值:

var name = "Marry";  //创建字符串
name.age = 20;       //添加名为age的属性,赋予number值20
alert(name.age);     //弹出"underfined"

  name字符串被添加了一个age属性,为其赋值20,但下次访问时这个属性就不见了。

  这说明只能给引用类型值动态地添加属性。

  复制变量值

  从变量a变量b复制基本类型的值,会在变量b对象上创建一个新值,将该值复制到给变量a分配的位置上,独立保存。这两个变量参与的任何操作都不会互相影响。

  若从变量c变量d复制引用类型的值,同样会将存储在变量d对象中的值复制一份放到为变量c分配的空间中,但这个值的副本实际是一个指针,与变量d指向堆内存中的同一个对象。两个变量实际引用同一个对象,改变其中一个变量,将影响另一个变量。

  具体区别见如下例子:

//基本类型值
var num1 = 5;var num2 = num1;
num2 = num2 + 5;
alert(num1);                   
//5alert(num2);                   
//10/
/引用类型值
var obj1 = new object();var obj2 = obj1;
obj1.name = "Marry";
alert(obj2.name);            
//"Marry"

  函数传参

  ECMAScript中所有函数的参数都是按值传递的,即将函数外部的值复制给函数内部的参数。鉴于基本类型值与引用类型值复制变量的不同,其函数传参的效果也不同。

  在向参数传递基本类型值时,被传递的参数被赋给一个局部变量,函数内部参数的变化不影响函数外部的变量;向参数传递引用类型值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化将会反映在函数的外部。如下列例子:

//传递基本类型值function addnum(num) {
    num += 10;    return num; 
}var num1 = 5;var num2 = addnum(num1);
alert(num1);                  
//5,无变化alert(num2);                  
//15//传递引用类型值
function setage(obj) {
    obj.age = 20;
}var obj1 = new object();
setage(obj1)
alert(obj1.age);            //20

在局部作用域中修改的对象反映在全局作用域中,很多人会以为这是按引用传递。但函数对象确实都是按值传递,见下列例子:

function setage(obj) {
    obj.age = 20;
    obj = new object();
    obj.age = 30;
}var obj1 = new object();
setage(obj1)
alert(obj1.age);           
//20

  此例中在函数内部为obj重新定义了一个对象,且为其age属性重新赋值,但这一变化并未反映在函数外部,说明obj1 并不是按引用传递的。实际函数内重新定义的对象为局部对象,在退出函数后就会被立即销毁。

  检测类型

  基本类型值可以通过typeof检测,但typeof检测引用类型时只能返回object。所以为了知道某个值是什么类型的对象,ECMAScript提供了instanceof操作符,语法如下:

result = variable instanceof constructor

如果变量是引用类型的实例,instanceof操作符就会返回true。

以上就是有关JavaScript变量相关问题详解的详细内容,更多请关注php中文网其它相关文章!

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。