上篇文章讲了 js 中的一些概念(词法结构) 和 数据类型(部分)。 <!----> <o:p> </o:p>
这章我们 继续 . 然后了解下 js 中操作数据 和 函数的 作用域。 <o:p> </o:p>
<o:p> </o:p>
1, 对象跟基本类型之间的转换: <o:p> </o:p>
不管何时,只是对象非空,在布尔环境中都为 true.<o:p></o:p>
如 ;<o:p></o:p>
new Boolean(false); <o:p></o:p>
new Number(0);<o:p></o:p>
new String(“”);<o:p></o:p>
new Array();<o:p></o:p>
上面虽然内部值是 false, 但对象的值是 true;<o:p></o:p>
Object à valueOf() à toString()<o:p></o:p>
其中 Date 类,是先执行 toString() 转换。 <o:p> </o:p>
<o:p> </o:p>
2,js 中操作一个数据值: <o:p> </o:p>
任何语言都有自己的操作数据的方法; <o:p> </o:p>
Js 也不例外, js 有 3 种重要的方式来操作一个数据值。 <o:p> </o:p>
1) 复制它。例如把它赋给一个新的变量。 <o:p> </o:p>
2) 把它作为参数传递给一个函数或方法。 <o:p> </o:p>
3) 可以和其他值比较大小。 <o:p> </o:p>
<o:p> </o:p>
Js 通过传值和传址 2 种方式操作这些数据的值。 <o:p> </o:p>
从名称可以看处,传值 是通过传递值来操作数据。在赋值的过程中,对实际的值进行了拷贝,存储到一个新的变量中。拷贝的值和原来的值是 2 份完全独立的值。所以如果你改变了拷贝的值,并不会影响原来的值。当比较大小时候,通常进行琢个字节比较。 <o:p> </o:p>
传址 从名字来看,就是通过传递地址来操作数据。在赋值的过程中,对实际的值的地址(可以说是引用)进行了拷贝,他们不是完全的独立,所以如果你通过引用改变了值,那么原始的值也会改变。当比较大小的时候,通常是看他们是否引用同一个地址来比较。 <o:p> </o:p>
简单的传址例子: <o:p> </o:p>
var a = new Date();<o:p></o:p>
alert(a.getDate());<o:p></o:p>
var b = a ;<o:p></o:p>
b.setDate(21);<o:p></o:p>
alert(a.getDate()) // 输出 21 <o:p></o:p>
<o:p> </o:p>
3, 一般来说: <o:p> </o:p>
基本数据类型通过传值来操作的。(如果忘记了哪些是基本数据类型,可以往回看。) <o:p> </o:p>
对象数据类型通过传址来操作的。(比如 数组和函数) <o:p> </o:p>
例子: <o:p> </o:p>
<script><o:p></o:p>
// 传值 <o:p> </o:p>
a=1;<o:p></o:p>
b=a;<o:p></o:p>
b=2;<o:p></o:p>
alert(a); // 输出 1<o:p></o:p>
<o:p> </o:p>
// 传址 <o:p> </o:p>
x=[1,2];<o:p></o:p>
y=x; // 赋给 y 的只是 x 的一个引用,而不是 x 本身。数组已经在语句中被赋值了,执行过这段代码后,仍旧只有一个数组对象,只不过我们有 2 个对他的引用了。 <o:p> </o:p>
y[0]=2;<o:p></o:p>
alert(x[0] +" | " +x[1]); // 输出 2 | 2<o:p></o:p>
</script><o:p></o:p>
其中我们必须注意字符串: <o:p> </o:p>
js 中字符串是通过传址来复制和传递的,而他们是通过传值来比较的。 <o:p> </o:p>
对象和数组是用传值来传递的,只不过传递的这个值实际是一个引用,而不是对象本身。 <o:p> </o:p>
总结 :<o:p></o:p>
类型 <o:p> </o:p> |
复制 <o:p> </o:p> |
传递 <o:p> </o:p> |
比较 <o:p> </o:p> |
数字 <o:p> </o:p> |
传值 <o:p> </o:p> |
传值 <o:p> </o:p> |
传值 <o:p> </o:p> |
布尔 <o:p> </o:p> |
传值 <o:p> </o:p> |
传值 <o:p> </o:p> |
传值 <o:p> </o:p> |
字符串 <o:p> </o:p> |
不可变 <o:p> </o:p> |
不可变 <o:p> </o:p> |
传值 <o:p> </o:p> |
对象 <o:p> </o:p> |
传址 <o:p> </o:p> |
传址 <o:p> </o:p> |
传址 <o:p> </o:p> |
不可变:在 JS 中,没有方法去改变字符串值的内容。 <o:p> </o:p>
对字符串来说,传值还是传址,意义不大。 <o:p> </o:p>
<o:p> </o:p>
4, 垃圾收集机制: <o:p> </o:p>
Js 中自动释放内存。 <o:p> </o:p>
比如: <o:p> </o:p>
var s =”heelo”;<o:p></o:p>
var b = s.toUpperCase();<o:p></o:p>
s=b; // 运行到这里后, js 会自动检测不再使用某个对象,因为 s=b 了,所以 js 会自动释放字符串“ heelo ”所占的存储空间。即我们不能再获取原始的 “heelo” 值; .<o:p></o:p>
<o:p> </o:p>
5 , javascript 变量: <o:p> </o:p>
Js 是非类型的。它的变量可以放任何类型的值。 <o:p> </o:p>
<o:p> </o:p>
变量的声明: <o:p> </o:p>
var a ;<o:p></o:p>
var b ;<o:p></o:p>
或者 <o:p> </o:p>
var a , b ;<o:p></o:p>
或者 <o:p> </o:p>
var a=0 , b=1 ;<o:p></o:p>
<o:p> </o:p>
重复声明 是合法的, <o:p> </o:p>
如果 遗漏声明 , js 会隐式的声明该变量。当然隐式声明的变量总是全局变量。 <o:p> </o:p>
<o:p> </o:p>
6 , 变量的作用域: <o:p> </o:p>
Js 有 2 种:全局和局部。 <o:p> </o:p>
从名字的定义可以知道,全局变量的作用域是全局性的。 <o:p> </o:p>
在 js 代码中,处处都有定义。 <o:p> </o:p>
局部变量的作用域是局部的。 <o:p> </o:p>
在函数体内定义。 <o:p> </o:p>
<o:p> </o:p>
同名的局部变量的优先级比同名的全局变量高,下面的例子说明了这点: <o:p> </o:p>
var a ="abc"; // 全局变量 <o:p> </o:p>
function check(){<o:p></o:p>
var a = "efg"; // 同名的局部变量 <o:p> </o:p>
document.write(a); <o:p></o:p>
}<o:p></o:p>
check(); // 输出 efg<o:p></o:p>
<o:p> </o:p>
看一个比较经典的例子 :<o:p></o:p>
var scope = "global";<o:p></o:p>
function f(){<o:p></o:p>
alert(scope); // 输出 undefined<o:p></o:p>
var scope = "local";<o:p></o:p>
alert(scope); // 输出 local<o:p></o:p>
}<o:p></o:p>
f();<o:p></o:p>
<o:p> </o:p>
为什么第一个会输出 undefined 呢? <o:p> </o:p>
因为 js 规定当 局部变量和全局变量的名称相同的时候,函数