- 浏览: 452387 次
- 性别:
- 来自: 西安
文章分类
最新评论
-
进退取舍:
谢谢,这个用上了!!
Java 一个线程池的示例 -
pb_water:
感谢楼主,打算买楼主的书,支持一下,楼主功德无量
JavaScript内核系列第0版整理稿下载 -
lancezhcj:
有图会直观的多呢,再摸索摸索
有限自动机与建模 -
hsmsyy:
这里应该是原创了吧,楼主我觉得闭包的作用:实现面向对象。有待商 ...
JavaScript内核系列 第7章 闭包 -
wll52:
在应用退出之前,需要释放连接 con.disconnect() ...
使用smack与GTalk通信
第二章 基本概念
本章将聚焦于JavaScript中的基本概念,这些概念与传统语言有比较大的不同,因此单独列出一章来做专门描述,理解本章的概念对书中后续章节的概念,代码的行为等会有很大的帮助,读者不妨花比较大的时间在本章,即使你对JavaScript已经比较熟悉,也建议通读本章。
本章主要讲述JavaScript中的数据类型(基本类型与引用类型),变量(包括变量的作用域),操作符(主要是一些较为常见,但是不容易从字面上理解的操作符)。由于JavaScript中的“一切皆对象”,在掌握了这些基本的概念之后,读者就可以较为轻松的理解诸如作用域,调用对象,闭包,currying等等较难理解的概念了。
2.1数据类型
有程序设计经验的读者肯定知道,在C或者Java这样的语言中,数据是有类型的,比如用以表示用户名的属性是字符串,而一个雇员的年龄则是一个数字,表示UI上的一个开关按钮的数据模型则为布尔值等等,对数字可能还可以细分为浮点数,整型数,整型数又可能分为长整型和短整型,总而言之,它们都表示语言中的数据的值的类型。
JavaScript中的数据类型分为两种:基本数据类型和对象类型,其中对象类型包含对象,数组,以及函数(事实上,函数,数组等也都是对象,这个在后边的章节详述)。
2.1.1 基本数据类型
在JavaScript中,包含三种基本的数据类型,字符串(String),数值(Number),布尔值(boolean),下面是一些简单的例子:
var str = "Hello, world";//字符串
var i = 10;//整型数
var f = 2.3;//浮点数
var b = true;//布尔值
我们可以分别查看变量的值及变量的类型:
print(str); print(i); print(f); print(b); print(typeof str); print(typeof i); print(typeof f); print(typeof b);
注意,在此处使用的print()函数为rhino解释器的顶层对象的方法,可以用来打印字符串,通常情况下,在客户端,程序员多使用alert()进行类似的动作,alert()是浏览器中JavaScript解释器的顶层对象(window)的一个方法。
Hello, world 10 2.3 true string number number Boolean
在JavaScript中,所有的数字,不论是整型浮点,都属于“数字”基本类型。typeof是一个一元的操作符,在本章的另外一个小节会专门讲到。
2.1.2 对象类型
这里提到的对象不是对象本身,而是指一种类型,我们在第三章会对对象进行详细的讨论,此处的对象包括,对象(属性的集合,即键值的散列表),数组(有序的列表),函数(包含可执行的代码)。
对象类型是一种复合的数据类型,其基本元素由基本数据类型组成,当然不限于基本类型,比如对象类型中的值可以是其他的对象类型实例,我们通过例子来说明:
var str = "Hello, world";
var obj = new Object();
obj.str = str;
obj.num = 2.3;
var array = new Array("foo", "bar", "zoo");
var func = function(){
print("I am a function here");
}
可以看到,对象具有属性,如obj.str, obj.num,这些属性的值可以是基本类型,事实上还可以更复杂,我们来看看他们的类型:
print(typeof obj); print(typeof array); print(typeof func); //将打印出 object object function
读者可能会对print(typeof array)打印出object感到奇怪,事实上,对象和数组的界限并不那么明显(事实上它们是属于同一类型的),但是他们的行为却非常不同,本书的后续章节将两个重要的数据类型做了分别介绍。
2.1.3 两者之间的转换
类似与Java中基本数据类型的自动装箱拆箱,JavaScript也有类似的动作,基本数据类型在做一些运算时,会临时包装一个对象,做完运算后,又自动释放该对象。我们可以通过几个例子来说明:
var str = "JavaScript Kernal";
print(str.length);//打印17
str为一个字符串,通过typeof运算符可知其type为”string”,而:
var str2 = new String("JavaScript Kernal");
print(typeof str2);
可知,str2的type为”object”,即这两者并不相同,那么为什么可以使用str.length来的到str的长度呢?事实上,当使用str.length时,JavaScript会自动包装一个临时的String对象,内容为str的内容,然后获取该对象的length属性,最后,这个临时的对象将被释放。
而将对象转换为基本类型则是通过这样的方式:通过调用对象的valueOf()方法来取得对象的值,如果和上下文的类型匹配,则使用该值。如果valueOf取不到值的话,则需要调用对象的toString()方法,而如果上下文为数值型,则又需要将此字符串转换为数值。由于JavaScript是弱类型的,所以JavaScript引擎需要根据上下文来“猜测”对象的类型,这就使得JavaScript的效率比编译型的语言要差一些。
valueOf()的作用是,将一个对象的值转换成一种合乎上下文需求的基本类型,toString()则名副其实,可以打印出对象对应的字符串,当然前提是你已经“重载”了Object的toString()方法。
事实上,这种转换规则会导致很多的问题,比如,所有的非空对象,在布尔值环境下,都会被转成true,比如:
function convertTest(){
if(new Boolean(false) && new Object() &&
new String("") && new Array()){
print("convert to boolean")
}
}
convertTest();//convert to Boolean
初学者容易被JavaScript中的类型转换规则搞晕掉,很多情况下会觉得那种写法看着非常别扭,其实只需要掌握了规则,这些古怪的写法会大大的提高代码的性能,我们通过例子来学习这些规则:
var x = 3;
var y = x + "2";// => 32
var z = x + 2;// => 5
print(y);
print(z);
通常可以在JS代码中发现这样的代码:
if(datamodel.item){
//do something...
}else{
datamodel.item = new Item();
}
这种写法事实上具有更深层次的含义:
应该注意到,datamodel.item是一个对象(字符串,数字等),而if需要一个boolean型的表达式,所以这里进行了类型转换。在JavaScript中,如果上下文需要boolean型的值,则引擎会自动将对象转换为boolean类型。转换规则为,如果该对象非空,则转换为true,否则为false.因此我们可以采取这种简写的形式。
而在传统的编程语言(强类型)中,我们则需要:
if(datamodel.item != null){
//do something...
}else{
datamodel.item = new Item();
}
2.1.4类型的判断
前面讲到JavaScript特性的时候,我们说过,JavaScript是一个弱类型的语言,但是有时我们需要知道变量在运行时的类型,比如,一个函数的参数预期为另一个函数:
function handleMessage(message, handle){
return handle(message);
}
当调用handleMessage的函数传递的handle不是一个函数则JavaScript引擎会报错,因此我们有必要在调用之前进行判断:
function handleMessage(message, handle){
if(typeof handle == "function"){
return handle(message);
}else{
throw new Error("the 2nd argument should be a function");
}
}
但是,typeof并不总是有效的,比如下面这种情况:
var obj = {};
var array = ["one", "two", "three", "four"];
print(typeof obj);//object
print(typeof array); //object
运行结果显示,对象obj和数组array的typeof值均为”object”,这样我们就无法准确判断了,这时候,可以通过调用instanceof来进行进一步的判断:
print(obj instanceof Array);//false print(array instanceof Array);//true
第一行代码返回false,第二行则返回true。因此,我们可以将typeof操作符和instanceof操作符结合起来进行判断。
2.2 变量
变量,即通过一个名字将一个值关联起来,以后通过变量就可以引用到该值,比如:
var str = "Hello, World";
var num = 2.345;
当我们下一次要引用”Hello, Wrold”这个串进行某项操作时,我们只需要使用变量str即可,同样,我们可以用10*num 来表示10*2.345。变量的作用就是将值“存储”在这个变量上。
2.2.1基本类型和引用类型
在上一小节,我们介绍了JavaScript中的数据类型,其中基本类型如数字,布尔值,它们在内存中都有固定的大小,我们通过变量来直接访问基本类型的数据。而对于引用类型,如对象,数组和函数,由于它们的大小在原则上是不受任何限制的,故我们通过对其引用的访问来访问它们本身,引用本身是一个地址,即指向真实存储复杂对象的位置。
基本类型和引用类型的区别是比较明显的,我们来看几个例子:
var x = 1;//数字x,基本类型
var y = x;//数字y,基本类型
print(x);
print(y);
x = 2;//修改x的值
print(x);//x的值变为2
print(y);//y的值不会变化
运行结果如下:
1
2
1
这样的运行结果应该在你的意料之内,没有什么特别之处,我们再来看看引用类型的例子,由于数组的长度非固定,可以动态增删,因此数组为引用类型:
var array = [1,2,3,4,5];
var arrayRef = array;
array.push(6);
print(arrayRef);
引用指向的是地址,也就是说,引用不会指向引用本身,而是指向该引用所对应的实际对象。因此通过修改array指向的数组,则arrayRef指向的是同一个对象,因此运行效果如下:
2.2.2变量的作用域
变量被定义的区域即为其作用域,全局变量具有全局作用域;局部变量,比如声明在函数内部的变量则具有局部作用域,在函数的外部是不能直接访问的。比如:
var variable = "out";
function func(){
var variable = "in";
print(variable);//打印”in”
}
func();
print(variable);//打印”out”
应该注意的是,在函数内var关键字是必须的,如果使用了变量而没有写var关键字,则默认的操作是对全局对象的,比如:
var variable = "out";
function func(){
variable = "in";//注意此variable前没有var关键字
print(variable);
}
func();
print(variable);//全局的变量variable被修改
由于函数func中使用variable而没有关键字var,则默认是对全局对象variable属性做的操作(修改variable的值为in),因此此段代码会打印:
in
2.3运算符
运算符,通常是容易被忽略的一个内容,但是一些比较古怪的语法现象仍然可能需要用到运算符的结合率或者其作用来进行解释,JavaScript中,运算符是一定需要注意的地方,有很多具有JS编程经验的人仍然免不了被搞得晕头转向。
我们在这一节主要讲解这样几个运算符:
2.3.1中括号运算符([])
[]运算符可用在数组对象和对象上,从数组中按下标取值:
var array = ["one", "two", "three", "four"];
array[0]
而[]同样可以作用于对象,一般而言,对象中的属性的值是通过点(.)运算符来取值,如:
var object = {
field : "self",
printInfo : function(){
print(this.field);
}
}
object.field;
object.printInfo();
但是考虑到这样一种情况,我们在遍历一个对象的时候,对其中的属性的键(key)是一无所知的,我们怎么通过点(.)来访问呢?这时候我们就可以使用[]运算符:
for(var key in object){
print(key + ":" + object[key]);
}
运行结果如下:
field:slef printInfo:function (){ print(this.field); }
2.3.2点运算符(.)
点运算符的左边为一个对象(属性的集合),右边为属性名,应该注意的是右边的值除了作为左边的对象的属性外,同时还可能是它自己的右边的值的对象:
var object = {
field : "self",
printInfo : function(){
print(this.field);
},
outter:{
inner : "inner text",
printInnerText : function(){
print(this.inner);
}
}
}
object.outter.printInnerText();
这个例子中,outter作为object的属性,同时又是printInnerText()的对象。
2.3.3 == 和 === 以及 != 和 !==
运算符==读作相等,而运算符===则读作等同。这两种运算符操作都是在JavaScript代码中经常见到的,但是意义则不完全相同,简而言之,相等操作符会对两边的操作数做类型转换,而等同则不会。我们还是通过例子来说明:
print(1 == true); print(1 === true); print("" == false); print("" === false); print(null == undefined); print(null === undefined);
运行结果如下:
true
false
true
false
true
false
相等和等同运算符的规则分别如下:
相等运算符
如果操作数具有相同的类型,则判断其等同性,如果两个操作数的值相等,则返回true(相等),否则返回false(不相等).
如果操作数的类型不同,则按照这样的情况来判断:
l null和undefined相等
l 其中一个是数字,另一个是字符串,则将字符串转换为数字,在做比较
l 其中一个是true,先转换成1(false则转换为0)在做比较
l 如果一个值是对象,另一个是数字/字符串,则将对象转换为原始值(通过toString()或者valueOf()方法)
l 其他情况,则直接返回false
等同运算符
如果操作数的类型不同,则不进行值的判断,直接返回false
如果操作数的类型相同,分下列情况来判断:
l 都是数字的情况,如果值相同,则两者等同(有一个例外,就是NaN,NaN与其本身也不相等),否则不等同
l 都是字符串的情况,与其他程序设计语言一样,如果串的值不等,则不等同,否则等同
l 都是布尔值,且值均为true/false,则等同,否则不等同
l 如果两个操作数引用同一个对象(数组,函数),则两者完全等同,否则不等同
l 如果两个操作数均为null/undefined,则等同,否则不等同
比如:
var obj = {
id : "self",
name : "object"
};
var oa = obj;
var ob = obj;
print(oa == ob);
print(oa === ob);
会返回:
true
再来看一个对象的例子:
var obj1 = {
id : "self",
name : "object",
toString : function(){
return "object 1";
}
}
var obj2 = "object 1";
print(obj1 == obj2);
print(obj1 === obj2);
返回值为:
false
obj1是一个对象,而obj2是一个结构与之完全不同的字符串,而如果用相等操作符来判断,则两者是完全相同的,因为obj1重载了顶层对象的toString()方法。
而!=不等和!==不等同,则与==/!==相反。因此,在JavaScript中,使用相等/等同,不等/不等同的时候,一定要注意类型的转换,这里推荐使用等同/不等同来进行判断,这样可以避免一些难以调试的bug。
附:由于作者本身水平有限,文中难免有纰漏错误等,或者语言本身有不妥当之处,欢迎及时指正,提出建议,参与讨论,谢谢大家!
评论
2.var obj = new Object();
3.obj.str = str;
4.obj.num = 2.3;
5.
6.var array = new Array("foo", "bar", "zoo");
7.
8.var func = function(){
9. print("I am a function here");
10.}
array 的类型是function func返回的是undefined
var bool = new Boolean(false);
var bool1 = false;
function cont(){
if(bool){ //if(bool1) 不执行
alert(bool)
}
}
这两种定义有什么区别,两者最后的值都false,为什么对象定义类型能执行???
这个跟JavaScript的类型判断/转换机制有关系:
var bool = new Boolean(false);//这是一个Boolean对象, if(bool){//此时判断bool是否为空或undefined,相当于if(bool == null || bool == undefined),因此返回true }
而对象直接量在判断是并非作为一个对象来判断的,简而言之,可以看下这两者在实际运行环境中的类型:
typeof bool1 boolean typeof bool object
bool1的值为false,因此不会执行,而bool为一个非空的对象,因此if会将其转换为true(相当于bool == null?)
var bool = new Boolean(false);
var bool1 = false;
function cont(){
if(bool){ //if(bool1) 不执行
alert(bool)
}
}
这两种定义有什么区别,两者最后的值都false,为什么对象定义类型能执行???
你可以试试obj.first_name,obj.first-name,obj["first-name"]
变量名中包含.只是非法变量名的一种。
我感觉这个有点绕,但应该不是“非法”的问题,解释器在解释到obj.first-name时,
不知道是obj的first属性来“减”name的值,还是obj.first-name。
根本原因应该是在[]操作符里,是以字符串做索引的,因此没有问题。而点操作符不是用字符串,而是
去遍历对象的属性列表(不是用字符串)而导致的。
你可以试试obj.first_name,obj.first-name,obj["first-name"]
变量名中包含.只是非法变量名的一种。
没有合法不合法之说吧?
如果属性中包含点号(.)则只能用[],没有点号的两者均可。
http://www.iteye.com/topic/646798
http://www.iteye.com/topic/641532
专栏地址如下:
http://www.iteye.com/wiki/javascript-core
第七章 闭包
7.1闭包的特性
7.2闭包的用途
7.3应该注意的问题
第八章 面向对象的Javascript
8.1 原型继承
8.1.1引用
8.1.2 new操作符
8.2封装与继承
8.3 工具包Base
8.4实例:事件分发器
第九章 函数式的Javascript
9.1匿名函数
9.2高阶函数
9.3闭包与Currying
9.4一些例子
谢谢关注,后边的章节基本已经完成,文字方面可能还需要润色,个别细节还需要斟酌,请耐心等待,呵呵。
第七章 闭包
7.1闭包的特性
7.2闭包的用途
7.3应该注意的问题
第八章 面向对象的Javascript
8.1 原型继承
8.1.1引用
8.1.2 new操作符
8.2封装与继承
8.3 工具包Base
8.4实例:事件分发器
第九章 函数式的Javascript
9.1匿名函数
9.2高阶函数
9.3闭包与Currying
9.4一些例子
你把整个文章贴一遍,是么子意思呢?
<div class="quote_div">
<p> </p>
<h2>
<a name="_Toc252397742"><span>第二章</span> </a><span><span>基本概念</span></span>
</h2>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>本章将聚焦于</span><span lang="EN-US">JavaScript</span><span>中的基本概念,这些概念与传统语言有比较大的不同,因此单独列出一章来做专门描述,理解本章的概念对书中后续章节的概念,代码的行为等会有很大的帮助,读者不妨花比较大的时间在本章,即使你对</span><span lang="EN-US">JavaScript</span><span>已经比较熟悉,也建议通读本章。</span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>本章主要讲述</span><span lang="EN-US">JavaScript</span><span>中的数据类型</span><span lang="EN-US">(</span><span>基本类型与引用类型</span><span lang="EN-US">)</span><span>,变量</span><span lang="EN-US">(</span><span>包括变量的作用域</span><span lang="EN-US">)</span><span>,操作符</span><span lang="EN-US">(</span><span>主要是一些较为常见,但是不容易从字面上理解的操作符</span><span lang="EN-US">)</span><span>。由于</span><span lang="EN-US">JavaScript</span><span>中的“<strong><em><span style="font-size: small;">一切皆对象</span></em></strong>”,在掌握了这些基本的概念之后,读者就可以较为轻松的理解诸如作用域,调用对象,闭包,</span><span lang="EN-US">currying</span><span>等等较难理解的概念了。</span></p>
<h3>
<a name="_Toc252397743"><span lang="EN-US">2.1</span></a><span><span>数据类型</span></span>
</h3>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>有程序设计经验的读者肯定知道,在</span><span lang="EN-US">C</span><span>或者</span><span lang="EN-US">Java</span><span>这样的语言中,数据是有类型的,比如用以表示用户名的属性是字符串,而一个雇员的年龄则是一个数字,表示</span><span lang="EN-US">UI</span><span>上的一个开关按钮的数据模型则为布尔值等等,对数字可能还可以细分为浮点数,整型数,整型数又可能分为长整型和短整型,总而言之,它们都表示语言中的数据的值的类型。</span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span lang="EN-US">JavaScript</span><span>中的数据类型分为两种:基本数据类型和对象类型,其中对象类型包含对象,数组,以及函数(事实上,函数,数组等也都是对象,这个在后边的章节详述)。</span></p>
<h4>
<a name="_Toc252397744"><span lang="EN-US">2.1.1 </span></a><span><span>基本数据类型</span></span>
</h4>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>在</span><span lang="EN-US">JavaScript</span><span>中,包含三种基本的数据类型,字符串</span><span lang="EN-US">(String)</span><span>,数值</span><span lang="EN-US">(Number)</span><span>,布尔值</span><span lang="EN-US">(boolean)</span><span>,下面是一些简单的例子:</span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var str = "Hello, world";//字符串
var i = 10;//整型数
var f = 2.3;//浮点数
var b = true;//布尔值</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>我们可以分别查看变量的值及变量的类型:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"> </p>
<p><span style="font-family: 'Courier New'; color: #0064c8; font-size: small;">
</span></p>
<pre name="code" class="js">print(str);
print(i);
print(f);
print(b);
print(typeof str);
print(typeof i);
print(typeof f);
print(typeof b);</pre>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>注意,在此处使用的</span><span style="font-size: 10.0pt;" lang="EN-US">print()</span><span>函数为</span><span style="font-size: 10.0pt;" lang="EN-US">rhino</span><span>解释器的顶层对象的方法,可以用来打印字符串,通常情况下,在客户端,程序员多使用</span><span style="font-size: 10.0pt;" lang="EN-US">alert()</span><span>进行类似的动作,</span><span style="font-size: 10.0pt;" lang="EN-US">alert()</span><span>是浏览器中</span><span style="font-size: 10.0pt;" lang="EN-US">JavaScript</span><span>解释器的顶层对象</span><span style="font-size: 10.0pt;" lang="EN-US">(window)</span><span>的一个方法。</span></p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"> </p>
<p><span style="font-family: 'Courier New'; font-size: small;">
</span></p>
<pre name="code" class="js">Hello, world
10
2.3
true
string
number
number
Boolean</pre>
<p> </p>
<p> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><span>在</span><span lang="EN-US">JavaScript</span><span>中,所有的数字,不论是整型浮点,都属于“数字”基本类型。</span><span lang="EN-US">typeof</span><span>是一个一元的操作符,在本章的另外一个小节会专门讲到。</span></p>
<h4>
<a name="_Toc252397745"><span lang="EN-US">2.1.2 </span></a><span><span>对象类型</span></span>
</h4>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>这里提到的对象不是对象本身,而是指一种类型,我们在第三章会对对象进行详细的讨论,此处的对象包括,对象</span><span lang="EN-US">(</span><span>属性的集合,即键值的散列表</span><span lang="EN-US">)</span><span>,数组</span><span lang="EN-US">(</span><span>有序的列表</span><span lang="EN-US">)</span><span>,函数</span><span lang="EN-US">(</span><span>包含可执行的代码</span><span lang="EN-US">)</span><span>。</span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>对象类型是一种复合的数据类型,其基本元素由基本数据类型组成,当然不限于基本类型,比如对象类型中的值可以是其他的对象类型实例,我们通过例子来说明:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 10.0pt;" lang="EN-US"> </span></strong></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var str = "Hello, world";
var obj = new Object();
obj.str = str;
obj.num = 2.3;
var array = new Array("foo", "bar", "zoo");
var func = function(){
print("I am a function here");
}</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>可以看到,对象具有属性,如</span><span lang="EN-US">obj.str, obj.num</span><span>,这些属性的值可以是基本类型,事实上还可以更复杂,我们来看看他们的类型:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"> </p>
<p><span style="font-family: 'Courier New'; color: #0064c8; font-size: small;">
</span></p>
<pre name="code" class="js">print(typeof obj);
print(typeof array);
print(typeof func);
//将打印出
object
object
function</pre>
<p> </p>
<p> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><span lang="EN-US"><span> </span></span><span>读者可能会对</span><span lang="EN-US">print(typeof array)</span><span>打印出</span><span lang="EN-US">object</span><span>感到奇怪,事实上,对象和数组的界限并不那么明显</span><span lang="EN-US">(</span><span>事实上它们是属于同一类型的</span><span lang="EN-US">)</span><span>,但是他们的行为却非常不同,本书的后续章节将两个重要的数据类型做了分别介绍。</span></p>
<h4>
<a name="_Toc252397746"><span lang="EN-US">2.1.3 </span></a><span><span>两者之间的转换</span></span>
</h4>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>类似与</span><span lang="EN-US">Java</span><span>中基本数据类型的自动装箱拆箱,</span><span lang="EN-US">JavaScript</span><span>也有类似的动作,基本数据类型在做一些运算时,会临时包装一个对象,做完运算后,又自动释放该对象。我们可以通过几个例子来说明:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 10.0pt;" lang="EN-US"> </span></strong></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var str = "JavaScript Kernal";
print(str.length);//打印17</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><span lang="EN-US">str</span><span>为一个字符串,通过</span><span lang="EN-US">typeof运算符</span><span>可知其</span><span lang="EN-US">type</span><span>为</span><span lang="EN-US">”string”</span><span>,而:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var str2 = new String("JavaScript Kernal");
print(typeof str2);</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>可知,</span><span style="font-size: 10.0pt;" lang="EN-US">str2</span><span>的</span><span style="font-size: 10.0pt;" lang="EN-US">type</span><span>为</span><span style="font-size: 10.0pt;" lang="EN-US">”object”</span><span>,即这两者并不相同,那么为什么可以使用</span><span style="font-size: 10.0pt;" lang="EN-US">str.length</span><span>来的到</span><span style="font-size: 10.0pt;" lang="EN-US">str</span><span>的长度呢?事实上,当使用</span><span style="font-size: 10.0pt;" lang="EN-US">str.length</span><span>时,</span><span style="font-size: 10.0pt;" lang="EN-US">JavaScript</span><span>会自动包装一个临时的</span><span style="font-size: 10.0pt;" lang="EN-US">String</span><span>对象,内容为</span><span style="font-size: 10.0pt;" lang="EN-US">str</span><span>的内容,然后获取该对象的</span><span style="font-size: 10.0pt;" lang="EN-US">length</span><span>属性,最后,这个临时的对象将被释放。</span></p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"><span> </span></span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>而将对象转换为基本类型则是通过这样的方式:通过调用对象的</span><span lang="EN-US">valueOf()</span><span>方法来取得对象的值,如果和上下文的类型匹配,则使用该值。如果</span><span lang="EN-US">valueOf</span><span>取不到值的话,则需要调用对象的</span><span lang="EN-US">toString()</span><span>方法,而如果上下文为数值型,则又需要将此字符串转换为数值。由于</span><span lang="EN-US">JavaScript</span><span>是弱类型的,所以</span><span lang="EN-US">JavaScript</span><span>引擎需要根据上下文来“猜测”对象的类型,这就使得</span><span lang="EN-US">JavaScript</span><span>的效率比编译型的语言要差一些。</span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span lang="EN-US">valueOf()</span><span>的作用是,将一个对象的值转换成一种合乎上下文需求的基本类型,</span><span lang="EN-US">toString()</span><span>则名副其实,可以打印出对象对应的字符串</span><span lang="EN-US">,</span><span>当然前提是你已经“重载”了</span><span lang="EN-US">Object</span><span>的</span><span lang="EN-US">toString()</span><span>方法。</span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>事实上,这种转换规则会导致很多的问题,比如,所有的非空对象,在布尔值环境下,都会被转成</span><span lang="EN-US">true</span><span>,比如:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 10.0pt;" lang="EN-US"> </span></strong></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">function convertTest(){
if(new Boolean(false) && new Object() &&
new String("") && new Array()){
print("convert to boolean")
}
}
convertTest();//convert to Boolean</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>初学者容易被</span><span lang="EN-US">JavaScript</span><span>中的类型转换规则搞晕掉,很多情况下会觉得那种写法看着非常别扭,其实只需要掌握了规则,这些古怪的写法会大大的提高代码的性能,我们通过例子来学习这些规则:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 10.0pt;" lang="EN-US"> </span></strong></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var x = 3;
var y = x + "2";// => 32
var z = x + 2;// => 5
print(y);
print(z);</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><span>通常可以在</span><span lang="EN-US">JS</span><span>代码中发现这样的代码:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 10.0pt;" lang="EN-US"> </span></strong></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">if(datamodel.item){
//do something...
}else{
datamodel.item = new Item();
}</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><span>这种写法事实上具有更深层次的含义:</span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>应该注意到,</span><span lang="EN-US">datamodel.item</span><span>是一个对象</span><span lang="EN-US">(</span><span>字符串,数字等</span><span lang="EN-US">)</span><span>,而</span><span lang="EN-US">if</span><span>需要一个</span><span lang="EN-US">boolean</span><span>型的表达式,所以这里进行了类型转换。在</span><span lang="EN-US">JavaScript</span><span>中,如果上下文需要</span><span lang="EN-US">boolean</span><span>型的值,则引擎会自动将对象转换为</span><span lang="EN-US">boolean</span><span>类型。转换规则为,如果该对象非空,则转换为</span><span lang="EN-US">true,</span><span>否则为</span><span lang="EN-US">false.</span><span>因此我们可以采取这种简写的形式。</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><span>而在传统的编程语言</span><span lang="EN-US">(</span><span>强类型</span><span lang="EN-US">)</span><span>中,我们则需要:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">if(datamodel.item != null){
//do something...
}else{
datamodel.item = new Item();
}</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<h4>
<a name="_Toc252397747"><span lang="EN-US">2.1.4</span></a><span><span>类型的判断</span></span>
</h4>
<p class="MsoNormal"><span>前面讲到</span><span lang="EN-US">JavaScript</span><span>特性的时候,我们说过,</span><span lang="EN-US">JavaScript</span><span>是一个弱类型的语言,但是有时我们需要知道变量在运行时的类型,比如,一个函数的参数预期为另一个函数:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">function handleMessage(message, handle){
return handle(message);
}</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>当调用</span><span style="font-size: 10.0pt;" lang="EN-US">handleMessage</span><span>的函数传递的</span><span style="font-size: 10.0pt;" lang="EN-US">handle</span><span>不是一个函数则</span><span style="font-size: 10.0pt;" lang="EN-US">JavaScript</span><span>引擎会报错,因此我们有必要在调用之前进行判断:</span></p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">function handleMessage(message, handle){
if(typeof handle == "function"){
return handle(message);
}else{
throw new Error("the 2nd argument should be a function");
}
}</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>但是,</span><span lang="EN-US">typeof</span><span>并不总是有效的,比如下面这种情况:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var obj = {};
var array = ["one", "two", "three", "four"];
print(typeof obj);//object
print(typeof array); //object</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>运行结果显示,对象</span><span lang="EN-US">obj</span><span>和数组</span><span lang="EN-US">array</span><span>的</span><span lang="EN-US">typeof</span><span>值均为</span><span lang="EN-US">”object”</span><span>,这样我们就无法准确判断了,这时候,可以通过调用</span><span lang="EN-US">instanceof</span><span>来进行进一步的判断:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"> </p>
<p><span style="font-family: 'Courier New'; color: #0064c8; font-size: small;">
</span></p>
<pre name="code" class="js">print(obj instanceof Array);//false
print(array instanceof Array);//true</pre>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>第一行代码返回</span><span lang="EN-US">false,</span><span>第二行则返回</span><span lang="EN-US">true</span><span>。因此,我们可以将</span><span lang="EN-US">typeof</span><span>操作符和</span><span lang="EN-US">instanceof</span><span>操作符结合起来进行判断。</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<h3>
<a name="_Toc252397748"><span lang="EN-US">2.2 </span></a><span><span>变量</span></span>
</h3>
<p class="MsoNormal"><span>变量,即通过一个名字将一个值关联起来,以后通过变量就可以引用到该值,比如:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 10.0pt;" lang="EN-US"> </span></strong></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var str = "Hello, World";
var num = 2.345;</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><span>当我们下一次要引用</span><span lang="EN-US">”Hello, Wrold”</span><span>这个串进行某项操作时,我们只需要使用变量</span><span lang="EN-US">str</span><span>即可,同样,我们可以用</span><span lang="EN-US">10*num </span><span>来表示</span><span lang="EN-US">10*2.345</span><span>。变量的作用就是将值“存储”在这个变量上。</span> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<h4>
<a name="_Toc252397749"><span lang="EN-US">2.2.1</span></a><span><span>基本类型和引用类型</span></span>
</h4>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>在上一小节,我们介绍了</span><span lang="EN-US">JavaScript</span><span>中的数据类型,其中基本类型如数字,布尔值,它们在内存中都有固定的大小,我们通过变量来直接访问基本类型的数据。而对于引用类型,如对象,数组和函数,由于它们的大小在原则上是不受任何限制的,故我们通过对其引用的访问来访问它们本身,引用本身是一个地址,即指向真实存储复杂对象的位置。</span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>基本类型和引用类型的区别是比较明显的,我们来看几个例子:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 10.0pt;" lang="EN-US"> </span></strong></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var x = 1;//数字x,基本类型
var y = x;//数字y,基本类型
print(x);
print(y);
x = 2;//修改x的值
print(x);//x的值变为2
print(y);//y的值不会变化</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>运行结果如下:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"> </p>
<p><span style="font-family: 'Courier New'; font-size: small;">
</span></p>
<div class="quote_div">1<br>1<br>2<br>1</div>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>这样的运行结果应该在你的意料之内,没有什么特别之处,我们再来看看引用类型的例子,由于数组的长度非固定,可以动态增删,因此数组为引用类型:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var array = [1,2,3,4,5];
var arrayRef = array;
array.push(6);
print(arrayRef);</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>引用指向的是地址,也就是说,引用不会指向引用本身,而是指向该引用所对应的实际对象。因此通过修改</span><span lang="EN-US">array</span><span>指向的数组,则</span><span lang="EN-US">arrayRef</span><span>指向的是同一个对象,因此运行效果如下:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"> </p>
<p><span style="font-family: 'Courier New'; font-size: small;">
</span></p>
<div class="quote_div">1,2,3,4,5,6</div>
<p> </p>
<p> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<h4>
<a name="_Toc252397750"><span lang="EN-US">2.2.2</span></a><span><span>变量的作用域</span></span>
</h4>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>变量被定义的区域即为其作用域,全局变量具有全局作用域;局部变量,比如声明在函数内部的变量则具有局部作用域,在函数的外部是不能直接访问的。比如:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 10.0pt;" lang="EN-US"> </span></strong></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var variable = "out";
function func(){
var variable = "in";
print(variable);//打印”in”
}
func();
print(variable);//打印”out”</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>应该注意的是,在函数内</span><span lang="EN-US">var</span><span>关键字是必须的,如果使用了变量而没有写</span><span lang="EN-US">var</span><span>关键字,则默认的操作是对全局对象的,比如:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var variable = "out";
function func(){
variable = "in";//注意此variable前没有var关键字
print(variable);
}
func();
print(variable);//全局的变量variable被修改</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>由于函数</span><span lang="EN-US">func</span><span>中使用</span><span lang="EN-US">variable</span><span>而没有关键字</span><span lang="EN-US">var,</span><span>则默认是对全局对象</span><span lang="EN-US">variable</span><span>属性做的操作</span><span lang="EN-US">(</span><span>修改</span><span lang="EN-US">variable</span><span>的值为</span><span lang="EN-US">in)</span><span>,因此此段代码会打印:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<div class="quote_div">in<br>in</div>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<h3>
<a name="_Toc252397751"><span lang="EN-US">2.3</span></a><span><span>运算符</span></span>
</h3>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>运算符,通常是容易被忽略的一个内容,但是一些比较古怪的语法现象仍然可能需要用到运算符的结合率或者其作用来进行解释,</span><span lang="EN-US">JavaScript</span><span>中,运算符是一定需要注意的地方,有很多具有</span><span lang="EN-US">JS</span><span>编程经验的人仍然免不了被搞得晕头转向。</span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>我们在这一节主要讲解这样几个运算符:</span></p>
<h4>
<a name="_Toc252397752"><span lang="EN-US">2.3.1中</span></a><span><span>括号运算符</span><span lang="EN-US">([])</span></span>
</h4>
<p class="MsoNormal"><span lang="EN-US"><strong><span style="color: #000080;">[]</span></strong></span><span>运算符可用在数组对象和对象上,从数组中按下标取值:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var array = ["one", "two", "three", "four"];
array[0]</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>而</span><span lang="EN-US">[]</span><span>同样可以作用于对象,一般而言,对象中的属性的值是通过点</span><span lang="EN-US">(.)</span><span>运算符来取值,如:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var object = {
field : "self",
printInfo : function(){
print(this.field);
}
}
object.field;
object.printInfo();</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>但是考虑到这样一种情况,我们在遍历一个对象的时候,对其中的属性的键</span><span style="font-size: 10.0pt;" lang="EN-US">(key)</span><span>是一无所知的,我们怎么通过点</span><span style="font-size: 10.0pt;" lang="EN-US">(.)</span><span>来访问呢?这时候我们就可以使用</span><span style="font-size: 10.0pt;" lang="EN-US">[]</span><span>运算符:</span></p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">for(var key in object){
print(key + ":" + object[key]);
}</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>运行结果如下:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"> </p>
<p><span style="font-family: 'Courier New'; font-size: small;">
</span></p>
<pre name="code" class="java">field:slef
printInfo:function (){
print(this.field);
}</pre>
<p> </p>
<p> </p>
<h4>
<a name="_Toc252397753"><span lang="EN-US">2.3.2</span></a><span><span>点运算符</span><span lang="EN-US">(.)</span></span>
</h4>
<p class="MsoNormal"><span>点运算符的左边为一个对象</span><span lang="EN-US">(</span><span>属性的集合</span><span lang="EN-US">)</span><span>,右边为属性名,应该注意的是右边的值除了作为左边的对象的属性外,同时还可能是它自己的右边的值的对象:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><span style="font-size: 13px;"><strong></strong></span></span></p>
<p><span style="font-family: 'Courier New'; color: #0000c8; font-size: small;"><strong>
</strong></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var object = {
field : "self",
printInfo : function(){
print(this.field);
},
outter:{
inner : "inner text",
printInnerText : function(){
print(this.inner);
}
}
}
object.outter.printInnerText();</pre>
</strong>
<p> </p>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>这个例子中,</span><span lang="EN-US">outter</span><span>作为</span><span lang="EN-US">object</span><span>的属性,同时又是</span><span lang="EN-US">printInnerText()</span><span>的对象。</span></p>
<h4>
<a name="_Toc252397754"><span lang="EN-US">2.3.3 == </span></a><span><span>和</span><span lang="EN-US"> === </span></span><span><span>以及</span><span lang="EN-US"> != </span></span><span><span>和</span><span lang="EN-US"> !==</span></span>
</h4>
<p> </p>
<p> </p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>运算符</span><span lang="EN-US">==</span><span>读作相等,而运算符</span><span lang="EN-US">===</span><span>则读作等同。这两种运算符操作都是在</span><span lang="EN-US">JavaScript</span><span>代码中经常见到的,但是意义则不完全相同,简而言之,相等操作符会对两边的操作数做类型转换,而等同则不会。我们还是通过例子来说明:</span><span lang="EN-US"><br><br></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; font-size: small;"><span style="font-size: 13px;">
</span></span></p>
<pre name="code" class="js">print(1 == true);
print(1 === true);
print("" == false);
print("" === false);
print(null == undefined);
print(null === undefined);</pre>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>运行结果如下:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #7f0055; font-size: small;"><span style="font-size: 13px;"><strong>
</strong></span></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">true
false
true
false
true
false</pre>
</strong>
<p> </p>
<p> </p>
<p class="MsoNormal"><strong><span style="font-size: 10.0pt;" lang="EN-US"> </span></strong></p>
<p class="MsoNormal"><span>相等和等同运算符的规则分别如下:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><strong><span>相等运算符</span></strong></p>
<p class="MsoNormal"><span>如果操作数具有相同的类型,则判断其等同性,如果两个操作数的值相等,则返回</span><span lang="EN-US">true(</span><span>相等</span><span lang="EN-US">)</span><span>,否则返回</span><span lang="EN-US">false(</span><span>不相等</span><span lang="EN-US">).</span></p>
<p class="MsoNormal"><span>如果操作数的类型不同,则按照这样的情况来判断:</span></p>
<p class="MsoNormal"><span style="font-family: Wingdings;" lang="EN-US"><span>l<span style="font: 7.0pt ;"> </span></span></span><span lang="EN-US">null</span><span>和</span><span lang="EN-US">undefined</span><span>相等</span></p>
<p class="MsoNormal"><span style="font-family: Wingdings;" lang="EN-US"><span>l<span style="font: 7.0pt ;"> </span></span></span><span>其中一个是数字,另一个是字符串,则将字符串转换为数字,在做比较</span></p>
<p class="MsoNormal"><span style="font-family: Wingdings;" lang="EN-US"><span>l<span style="font: 7.0pt ;"> </span></span></span><span>其中一个是</span><span lang="EN-US">true</span><span>,先转换成</span><span lang="EN-US">1(false</span><span>则转换为</span><span lang="EN-US">0)</span><span>在做比较</span></p>
<p class="MsoNormal"><span style="font-family: Wingdings;" lang="EN-US"><span>l<span style="font: 7.0pt ;"> </span></span></span><span>如果一个值是对象,另一个是数字</span><span lang="EN-US">/</span><span>字符串,则将对象转换为原始值</span><span lang="EN-US">(</span><span>通过</span><span lang="EN-US">toString()</span><span>或者</span><span lang="EN-US">valueOf()</span><span>方法</span><span lang="EN-US">)</span></p>
<p class="MsoNormal"><span style="font-family: Wingdings;" lang="EN-US"><span>l<span style="font: 7.0pt ;"> </span></span></span><span>其他情况,则直接返回</span><span lang="EN-US">false</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><strong><span>等同运算符</span></strong></p>
<p class="MsoNormal"><span>如果操作数的类型不同,则不进行值的判断,直接返回</span><span lang="EN-US">false</span></p>
<p class="MsoNormal"><span>如果操作数的类型相同,分下列情况来判断:</span></p>
<p class="MsoNormal"><span style="font-family: Wingdings;" lang="EN-US"><span>l<span style="font: 7.0pt ;"> </span></span></span><span>都是数字的情况,如果值相同,则两者等同</span><span lang="EN-US">(</span><span>有一个例外,就是</span><span lang="EN-US">NaN</span><span>,</span><span lang="EN-US">NaN</span><span>与其本身也不相等</span><span lang="EN-US">)</span><span>,否则不等同</span></p>
<p class="MsoNormal"><span style="font-family: Wingdings;" lang="EN-US"><span>l<span style="font: 7.0pt ;"> </span></span></span><span>都是字符串的情况,与其他程序设计语言一样,如果串的值不等,则不等同,否则等同</span></p>
<p class="MsoNormal"><span style="font-family: Wingdings;" lang="EN-US"><span>l<span style="font: 7.0pt ;"> </span></span></span><span>都是布尔值,且值均为</span><span lang="EN-US">true/false</span><span>,则等同,否则不等同</span></p>
<p class="MsoNormal"><span style="font-family: Wingdings;" lang="EN-US"><span>l<span style="font: 7.0pt ;"> </span></span></span><span>如果两个操作数引用同一个对象</span><span lang="EN-US">(</span><span>数组,函数</span><span lang="EN-US">)</span><span>,则两者完全等同,否则不等同</span></p>
<p class="MsoNormal"><span style="font-family: Wingdings;" lang="EN-US"><span>l<span style="font: 7.0pt ;"> </span></span></span><span>如果两个操作数均为</span><span lang="EN-US">null/undefined</span><span>,则等同,否则不等同</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><span>比如:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #7f0055; font-size: small;"><span style="font-size: 13px;"><strong>
</strong></span></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var obj = {
id : "self",
name : "object"
};
var oa = obj;
var ob = obj;
print(oa == ob);
print(oa === ob);</pre>
</strong>
<p> </p>
<p> </p>
<p class="MsoNormal"><span style="font-size: 10.0pt;" lang="EN-US"> </span></p>
<p class="MsoNormal"><span>会返回:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #7f0055; font-size: small;"><span style="font-size: 13px;"><strong>
</strong></span></span></p>
<p><strong>
</strong></p>
<strong>
<div class="quote_div">true<br>true</div>
</strong>
<p> </p>
<p> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><span>再来看一个对象的例子:</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 10.0pt;" lang="EN-US"> </span></strong></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #7f0055; font-size: small;"><span style="font-size: 13px;"><strong>
</strong></span></span></p>
<p><strong>
</strong></p>
<strong>
<pre name="code" class="js">var obj1 = {
id : "self",
name : "object",
toString : function(){
return "object 1";
}
}
var obj2 = "object 1";
print(obj1 == obj2);
print(obj1 === obj2);</pre>
</strong>
<p> </p>
<p> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal"><span>返回值为:</span></p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-family: 'Courier New'; color: #7f0055; font-size: small;"><span style="font-size: 13px;"><strong>
</strong></span></span></p>
<p><strong>
</strong></p>
<strong>
<div class="quote_div">true<br>false</div>
</strong>
<p> </p>
<p> </p>
<p class="MsoNormal"><span lang="EN-US"> </span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span lang="EN-US">obj1</span><span>是一个对象,而</span><span lang="EN-US">obj2</span><span>是一个结构与之完全不同的字符串,而如果用相等操作符来判断,则两者是完全相同的,因为</span><span lang="EN-US">obj1</span><span>重载了顶层对象的</span><span lang="EN-US"><strong><em>toString()</em></strong></span><span>方法。</span></p>
<p class="MsoNormal" style="text-indent: 21.0pt;"><span>而</span><span lang="EN-US">!=</span><span>不等和</span><span lang="EN-US">!==</span><span>不等同,则与</span><span lang="EN-US">==/!==</span><span>相反。因此,在</span><span lang="EN-US">JavaScript</span><span>中,使用相等</span><span lang="EN-US">/</span><span>等同,不等</span><span lang="EN-US">/</span><span>不等同的时候,一定要注意类型的转换,这里<strong>推荐使用等同</strong></span><span lang="EN-US"><strong>/</strong></span><span><strong>不等同</strong>来进行判断,这样可以避免一些难以调试的</span><span lang="EN-US">bug</span><span>。</span></p>
<p> </p>
<p class="MsoNormal" style="text-indent: 21.0pt;"> </p>
<p class="MsoNormal" style="text-indent: 21.0pt;"> </p>
<p><span><strong style="font-weight: bold;">附:由于作者本身水平有限,文中难免有纰漏错误等,或者语言本身有不妥当之处,欢迎及时指正,提出建议,参与讨论,谢谢大家!</strong></span></p>
</div>
<p> </p>
期待下一章
[quote]l 其中一个是true,先转换成1(false则转换为0)在做比较
这句话应该是真对一个操作数是true或false,另一个操作数是数字而言的。
对于一个操作数是布尔值、另一个操作数是字符串类型的相等运算,LZ最好也要说明下。这时在Firefox下,“1”为true,“”空字符串、“0”及其它字符串均为false,其它浏览器没有测试。
对于对象类型的操作数与原始类型的操作数作相等运算的情况,对象将通过valueOf()或toString()方法转化为原始类型然后再做比较,其中valueOf方法优先,LZ应该说明这个情况。
嗯,关于第一点,我是没有把前提条件描述清楚。
至于Firefox/其他浏览器对JS引擎实现上的差别,在目前的部分还不存在,因为还没有涉及到与浏览器相关的内容,因此叫“内核”,目前用的JS引擎为Rhino(是一个Java版的实现)。
valueOf()和toString()的优先问题,确实是我忽略掉了,谢谢你的提醒。
[quote]l 其中一个是true,先转换成1(false则转换为0)在做比较
这句话应该是真对一个操作数是true或false,另一个操作数是数字而言的。
对于一个操作数是布尔值、另一个操作数是字符串类型的相等运算,LZ最好也要说明下。这时在Firefox下,“1”为true,“”空字符串、“0”及其它字符串均为false,其它浏览器没有测试。
对于对象类型的操作数与原始类型的操作数作相等运算的情况,对象将通过valueOf()或toString()方法转化为原始类型然后再做比较,其中valueOf方法优先,LZ应该说明这个情况。
楼主继续更新~~~ 期待下期~
--Jason
不是很懂。看的云里雾里的。
发表评论
-
JavaScript内核系列 第15章 服务器端的JavaScript
2012-02-12 21:39 2325第15章已经在icodeit上发布,这一章分为上/下两篇,请朋 ... -
使用vim开发python及graphviz绘图
2011-12-23 14:49 6458基本需求 使用vim中的autocmd命令可以很容易的将正在 ... -
Java脚本技术应用实例
2011-01-22 11:24 4268前言 一直以来都很喜欢可以自由扩展的软件,这一点应该已经在很 ... -
可编程计算器(phoc)的设计与实现
2011-01-17 11:34 1983前言 借助JavaScript脚本 ... -
函数式编程(javascirpt)
2009-04-18 22:18 1264前言 Javascript,有人称 ... -
C和指针
2009-05-21 23:15 1117前言 指针是C的灵魂,正是指针使得C存在了这么多年,而且将长 ... -
C和指针(续)
2009-05-25 23:41 1360前言 上一篇《C和指针》可能对关于C和指针的有些内容没有说透 ... -
有限自动机与建模
2009-06-06 10:48 1786前言 在学校学程序设计语言的时候,能接触到的所有例子没有一个 ... -
事件和监听器
2009-06-21 22:06 1437前言 事件监听器是经 ... -
基于总线的消息服务(BBMS)的设计与实现
2009-07-25 22:19 1364前言 异步事件的通知机制在比较有规模的软件设计中必然会有涉及 ... -
JavaScript内核系列 第9章 函数式的Javascript
2010-05-13 19:20 3787第九章 函数式的Javascript 要说Ja ... -
JavaScript内核系列 第8章 面向对象的JavaScript(下)
2010-05-06 09:40 3673接上篇:JavaScript内核系列 第8章 面向对象的Jav ... -
JavaScript内核系列 第8章 面向对象的JavaScript(上)
2010-05-06 09:26 2906第八章 面向对象的 Javascript ... -
JavaScript内核系列 第7章 闭包
2010-05-04 08:48 3874第七章 闭包 闭包向来给包括JavaScript程序 ... -
JavaScript内核系列 第6章 正则表达式
2010-04-27 19:44 4050第六章 正则表达式 正则表达式是对字符串的结构 ... -
JavaScript内核系列 第5章 数组
2010-04-24 15:17 4531第五章 数组 JavaScript的数组也是一个比较 ... -
Swing小应用(Todo-List)之三
2010-04-22 20:47 2136前言 去年9月份开发的那个小工具sTodo,只是做到了能用, ... -
JavaScript内核系列 第4章 函数
2010-04-18 17:31 5095第四章 函数 函数,在C语言之类的过程式语言中 ... -
JavaScript内核系列 第3章 对象与JSON
2010-04-12 09:12 6134第三章 对象与JSON JavaScript对象与传 ... -
JavaScript内核系列 第1章 前言及概述
2010-04-01 23:15 9971前言 从2006年第一次接触JavaScript至今,算来也 ...
相关推荐
### JavaScript内核系列知识点概述 #### 一、JavaScript发展历程与特性 **JavaScript简史:** JavaScript的历史始于20世纪90年代,随着互联网的发展,静态网页已无法满足日益增长的用户交互需求。1996年,网景公司...
第二部分则是“jQuery内核详解与实践”,对jQuery的核心机制进行了深入剖析。 在“犀利开发”部分,作者可能涵盖了诸如高效编写JavaScript代码的方法,如何优化DOM操作,事件处理的最佳实践,以及如何利用jQuery...
理解其基本语法、数据类型、运算符和控制结构是掌握JavaScript的第一步,随着学习深入,还可以涉及函数、对象、数组、模块化、异步编程等更高级的概念,进一步提升Web开发能力。对于面试者来说,扎实的JavaScript...
第2章 01 上节课复习 02 arp协议复习 03 字符编码 第3章 01 网络基础和dos命令 02 为何学习linux 03 课程内容介绍 04 操作系统内核与系统调用 05 操作系统安装原理 06 linux操作系统安装 07 初识linux命令 08 ...
首先,书中的"核心技巧"部分涵盖了从基本语法到高级特性的广泛话题。例如,理解PHP的数据类型,如字符串、数组、对象和引用的用法,以及如何有效地操作它们。此外,书中可能会讨论变量作用域、函数与方法的定义与...
- **Chrome**: 使用**Blink**内核(自2013年起由WebKit分叉而来)结合**V8** JavaScript引擎。 - **Internet Explorer (IE)**/**Edge**: 分别使用**Trident**内核和**EdgeHTML**内核。 - **Firefox**: 使用**...
第2章 基本概念 2.1 Android的系统架构 2.1.1 Linux内核 2.1.2 本机库 2.1.3 Android运行时 2.1.4 应用程序框架 2.1.5 应用程序和小部件 2.2 它还活着 2.2.1 进程不等于应用程序 2.2.2 应用程序生命周期 2.3 构建块 ...
**第二章:如何开始** - **安装和配置开发环境**:介绍了如何安装 Eclipse IDE 和 Android SDK,并进行必要的环境配置。 - **创建 Android 项目**:指导读者通过 Eclipse 创建第一个 Android 项目。 - **调试和测试...
在易语言中调用Edge浏览器内核,首先需要理解的是进程通信(Process Communication)的概念。因为浏览器是一个独立的进程,而你的易语言程序是另一个进程,所以你需要通过某种方式让它们之间进行数据交换。这通常...
【PHP仿宝鸡第一人才网】是一个基于【骑士CMS】内核构建的在线招聘与求职平台。这个项目的主要特点是其美观的界面设计,为用户提供了良好的交互体验。在深入理解这个项目之前,我们需要先了解几个核心概念。 1. **...
* 第二轮复习:计算机基础知识、操作系统、计算机网络、Office2003、网页设计、多媒体技术 * 第三轮复习:计算机基础知识、操作系统、计算机网络、Office2003、网页设计、多媒体技术 本计划旨在提供一个系统、完整...
CSS2.0是其第二个主要版本,引入了浮动布局、定位、负边距、透明度等特性,极大地增强了网页设计的灵活性和控制力。在`css2.0中文手册.chm`中,你可以找到关于选择器、盒模型、定位、颜色、字体、边框和背景等所有...
【标题】"TP框架内核高仿蓝奏云网盘源码"涉及到的是基于ThinkPHP(简称TP)框架开发的一款类似蓝奏云的网盘系统源代码。这个系统旨在提供一个平台,用户可以上传、存储并分享文件,同时具备网赚功能和VIP服务,能够...
JavaScript的异步编程、DOM操作、事件处理等基本概念和高级特性可能都有所涉及。 4. **实例代码分析**:每个"exx"文件名可能是书中某个章节的示例代码,如ex1可能是第一章的代码,ex10可能是第十章的代码。这些代码...
第2章 Subversion中的增量编辑器:像本体一样的接口 2.1 版本控制与目录树的转换 2.2 表达目录树的差异 2.3 增量编辑器接口 2.4 但这是不是艺术? 2.5 像体育比赛一样的抽象 2.6 结论 第3章 我编写过的最漂亮代码 ...
《Linux系统管理技术手册(第二版)》作为一本全面介绍Linux系统管理知识的手册,不仅覆盖了基本概念和技术要点,还深入探讨了许多高级主题。无论是初学者还是有经验的技术人员,都可以从中获得实用的信息和技巧,...
要深入理解并利用这个源码,开发者需要熟悉PHP语法,了解基本的Web开发概念,以及可能涉及的前端技术和数据库管理。同时,阅读和理解源码的注释、结构和逻辑也是必要的。对于初学者,这是一个很好的实践项目,可以...