js基础--javascript基础概念之变量、作用域
javascript按照ECMA-262 的定义,变量与其他语言变量有所不同。js变量时松散的,不需要事先定义变量类型的。这使得他只是一个保存特定值的一个名称。变量与其数据类型可以在脚本的生命周期内改变。
还有明白几点:
JavaScript的变量作用域是基于其特有的作用域链的,JavaScript没有块级作用域。
基本类型和引用类型的值
ECMAScript 的变量有两种不同的数据类型;分别是 基本数据类型值 和 引用类型值 :
基本数据类型值
是指简单的数据段,
如 string number boolean undefined null 等都是简单是数据类型
引用类型值
是指由多个值构成的对象
object 是引用数据类型
动态的属性
定义基本类型的值和引用类型的值方式是类似的。创建一个变量并未变量赋值,但是赋了不同类型值之后,这个变量的意义就发生了巨大的变化。如:
var str = 'hello';//自动形成String类型 var obj = new Object();//Object 类型
定义了两个类型的变量。一个是简单类型的,一个是object类型的值。当你进行以下操作时:
str.name = 'kin'; obj.name = 'kin'; alert(str.name);//undefined alert(obj.name);//kin
通过给刚定义的变量添加属性。给string 类型的变量添加属性时并没有发生错误。但是访问是确实是未定义的状态。而引用类型的正常访问。这说明了只能够给引用类型的变量添加动态的属性。
关于变量声明
js声明变量有两个方法;一种是隐式声明,显式声明
var str = 'hello';//显式声明 hid = 'hello';//隐式声明
在外围作用域中,使用var关键字声明的显式变量被js引擎认为是全局变量。而在函数内使用var 定义的显式变量被认为是函数的局部变量。
事实上使用var定义的变量都是局部变量,在乎于作用域的问题。在外围作用域,被视为全局变量。在函数作用域 被视为局部变量。
当你访问一个没有赋值的变量是 js会报错,但是你给一个没有定义的变量赋值:
hid = 'hello';
js会认为你在进行隐式声明一个变量。
隐式和显式定义变量会有什么不同呢?
显式定义后的变量不能够操作delect 如:
var str = 'hello'; hid = 'hi'; alert(delete str);//false alert(delete hid);//true alert(str);//hello alert(hid);//undefined
全局变量和局部变量
在js解析器开始执行时,会在执行环境里建一个全局对象。在全局对象里面所定义的变量都是全局变量。因此,在顶层的代码里我们可以使用this window 等对象去访问这些变量:
var str = 'string'; alert(this.str);//string alert(window.str);//string function fun(){ alert(window.str);//string alert(this.str);//string } fun();
使用this 和 window 关键字可以对全局变量进行访问。可以直接访问
var Num = 100;//定义全局变量 function R_Num(){ alert(Num);//在函数作用域中访问全局变量 } R_Num();
复制变量
在js中 如果你要复制变量。非常简单如:
var str = ‘string’; var str1 = str;//此时 str1 等到了和str 一样的值;
在str 中保存的是字符串 string 定义str1 时使用str 来初始化。因此,str1 中也保存了str 相同的值。而str1 中的值是完全独立的,换句话说 就算你把str 删除 对str1 是没有任何影响的。可以说str1 是str 的一个副本。
例图:
标示符 | 值 |
str | string |
复制之后:开辟了一块新的空间保存str1
标示符 | |
str | string |
str1 | string |
复制引用类型的变量。实质上是复制引用类型的指针。如
var obj = new Object(); var obj2 = obj;
他们指向同一个引用类型。
传递参数
前面说道 js中传递到函数去的值都是保存的一个arguments 对象中去的。 所以,当有传递变量时同样涉及到把一个变量赋值到另外一个变量中去,如:
var num = 100; function addTen(num){ return num = num+100;//函数中改变了num变量。 } alert(addTen(num));//200 alert(num);//100
在函数内将num值改变了。
但是当回到外围作用域使用alert(num)时值依然是原来的值没有变化。说明当传递参数给函数时参数只是将num 复制传递到函数体内 函数中使用的只是外围作用域中num的副本。所以,在函数内部num改变都不会影响到函数外的num。
当传递的值是引用类型时。
如:
var obj = { name:'kin', age:'20' }; function changeName(obj){ return obj.name = 'chen'; } var newName = changeName(obj); alert(newName);//chen alert(obj.name);//chen
引用类型的值完全发生了变化 外围作用域中obj 的 name属性从原本的kin 改变成了chen 原因是传递给函数的值是这个引用类型的指针,函数根据这个指针改变了相应的obj属性。因此,obj的属性从根本上被改变了。