JavaScript语言精髓(1)之语法概要拾遗(转)

逻辑运算

JavaScript中支持两种逻辑运算,“逻辑或(||)”和“逻辑与(&&)”,他们的使用方法与基本的布尔运算一致:

var str= ‘hello’;
var obj = {};
x = str || obj;
y = str && obj;

这种运算符的特殊之处在于,他既不改变运算元的数据类型,也不强制运算结果的数据类型。除此之外,还有两条特性:

  • 运算符会将运算元理解为布尔值;
  • 运算过程支持布尔短路。

因此上例中,

x运算结果为:str;

y运算结果为:obj。

比较运算

1.等值检测

等值检测的目的是判断两个变量是否相等或相同。

相等是指运算符“==”和“!=”,相同是指运算符“===” 和"!=="。


名称


运算符


说明


相等


==


比较两个表达式,看是否相等。


不等


!=


比较两个表达式,看是否不相等


相同


===


比较两个表达式,看值是否相等并具有相同的数据类型。


不同


!==


比较两个表达式,看是否具有不相等的值或不同的数据类型。

等值检测中“相等”的运算规则


类型


运算规则


两个值类型进行比较


转换成相同数据类型的值进行“数据等值”比较。


值类型与引用类型进行比较


将引用类型的数据转换成为与值类型数据相同的数据,再进行“数据等值”比较。


两个引用类型比较


比较引用地址。

等值检测中“相同”的运算规则


类型


运算规则


两个值类型进行比较


如果数据类型不同,则必然“不相同”;数据类型相同时,进行“数值等值”比较。


值类型与引用类型进行比较


必然“不相同”。


两个引用类型比较


比较引用地址。

特别举例说明引用类型的等值比较,“比较引用地址” 的实际意义是:如果不是同一个变量或其引用,则两个变量不相等,也不相同。

var str = ‘abcdef‘;
var obj1 = new String(str);
var obj2 = new String(str);

alert(obj1==obj2);//返回false
alert(obj1===obj2);//返回false

“===“和“!==”运算符的一般性用途

在JavaScript中false、‘’、0和Null、undefined是两两“相等”的:

alert(‘‘==0);
alert(0==false);
alert(false==‘‘);
alert(undefined==null);

以上的结果都是true,因此当比较的数据元中包含以上5种情况时,应使用“===”和“!==”。

PS:一个值应该与其自身“相等/相同”,但存在一个例外:一个NaN值,与自身不相等,也不相同。

2.序列比较(比较大小)


可比较序列的类型


序列值


Boolean


0~1


String


Number


负无穷大~正无穷大


类型


运算规则


两个值类型进行比较


直接比较数据在序列中的大小。


值类型与引用类型进行比较


将引用类型的数据转换为与值类型数据相同的数据,再进行“序列大小”比较。


两个引用类型比较


无意义。(*注1)

注1:其实,对引用类型进行序列检测运算仍然是等可能的,但这与valueOf()运算的效果有关。

以下是上述的例子:

//值类型的比较,布尔值与数值
var b0 = false;
var b1 = true;
var num = 1;
alert(b1<num);//false
alert(b1<=num);//true
alert(b1>b0);//true

//值类型与引用类型
var num = 1;
var ref = new String();
alert(num > ref);//true

//引用类型的比较
var o1={};
var o2={};
alert(o1 > o2 || o1 < o2  || o1 == o2);//false

//两个运算元都是字符串,比较字符串中每个字符的大小
var s1 = "abc";
var s2 = "ab";
alert(s1 > s2);//true

//当字符串与其他类型值比较时,将字符串转换为数值比较
var s3 = "101";
var i= "100";
alert(s3 > i);true

//当字符串转换为数值时得到NaN,任何数据与NaN比较都为false
var s4 = "abc";
var i = "100";
alert(s4 > i);

 void运算符

使用void的语法格式是:[void 表达式]。

其作用是使后面的表达式立即执行,但忽略返回值(返回undefined)。

以下的例子很好的诠释了这句话的含义:

var s1 = "1";
function testVoid()
{
   s1 = "2";
}
var s2 = void testVoid();
alert(s1);//2
alert(s2);//undefined

利用这种特性,我们可以使<a>标签中的Href属性失去作用,就像我们常看到的那样:

这里void后的括号并不是必须的,只不过它仍然满足[void 表达式]这一语法格式,表达式等于(0)而已,千万不要当成了函数调用。

由此应该可以想到,既然这里使用到的是void 忽略返回值这一特性,那么该链接么有执行默认行为的原因并不是我们原以为的0在起作用,如下形式会得到同样的效果:

<a href="javascript: void 1">I am a useless link</a>
<a href="javascript: void ‘abcde‘">I am a useless link</a>
<a href="javascript: void (1 + 2)">I am a useless link</a> <!-- 这里不加括号行不行呢,大家自己去验证吧~  -->

函数调用

最常用的函数调用方式:

//具名函数直接调用
function foo()
{

}
foo();

//匿名函数通过引用来调用
var fooRef = function(){}
fooRef();

下面来看看几种不常见的函数调用方式:

//没有引用的匿名函数调用1
( //这里的括号对表示强制运算符 
  function()
  {
    alert(‘test‘);
  }()//这里的括号对表示函数调用运算符 (*注)
);
//执行完后,弹出‘test’表明函数执行成功。
下面来分析一下这段代码,首先来看内部的函数,
function()
{
  alert(‘test‘);
}()
这样还不够清晰,这段代码等同于
function fun1()
{
  alert(‘test‘);
}()
如果还觉得不够清晰的话,其实它还等同于
function fun1()
{
  alert(‘test‘);
};
();
也就是说第1个分号前的函数申明是作为完整的语法结构被解释,而后面的“();”则显然是一段错误的语法,
那么是什么让上面的函数调用得以成功执行呢?答案是最外层的强制运算符。
我们知道强制运算符是把本不会产生运算关系的运算元强制进行运算,比如:1*2+3*4,不会按照2+3这样的逻辑进行运算,但1*(2+3)*4之后就可以了。
回到上面的例子,最外层的强制运算符把本应单独解释的两段语句强制执行,执行的效果就是产生函数调用!

//没有引用的匿名函数调用2
(
   function()
   {
    }
)();//这里的括号对表示函数调用运算符 (*注)
经过上面的例子,这个就比较好理解了。
这里强制运算符运算的是“函数直接量声明”这个表达式,并返回一个函数的引用,然后通过函数调用运算符“()”来操作这个函数引用。

//没有引用的匿名函数调用3
void function()
{

}();//这里的括号对表示函数调用运算符 (*注)
运算符void用于使其后的函数表达式执行运算,可理解为一种强制运算,类似示例1。

上面3个例子中标(*注)的地方都是函数调用运算符,既然是函数调用的语法,那么和普通的函数调用一样,也是可以传递参数的。

void function(s)
{
  alert(s);
}(‘test‘);

 break的不常见用法

一般情况下,break子句作用于循环语句的内层或者switch语句中,但break子句也具有一种扩展的语法,以指示它所作用的范围。

该范围用已经声明过的标签来表示:

break some_label;

some_label:
{
   var s1 = "1";

if(s1 =="1")
   {
      break some_label;
   }
   s1 ="2";

}
alert(s1);// 结果为1,表明s1 ="2"并没有执行。

continue的不常见用法

continue后面也可以带一个标签,这时它表明从循环体内部中止,并继续到标签指示处开始执行。

some_label:
for(var i = 1; i <3;i++)
{
    for(var k =11; k < 13;k++)
    {
    if(k==12)
    {
        continue some_label;
    }
    alert("i = " + i + ";k = " + k);
    }
}
//依次弹出i = 1;k = 11  i = 2;k = 11
//直接看代码不容易理解,可以加个断点调试一下,其实这里的continue some_label的意义是从内部循环中跳出来,
//并继续执行外部的下一次循环,普通的continue是执行当前循环的下一次循环。
//这里需要注意的是continue对应的标签后不能添加大括号。

JavaScript中没有GOTO语句,break和continue语句提供了另一种选择的可能。

运算符的二义性

一、加号“+”的二义性

加号作为运算符在JavaScript中有三种作用:

1.字符串连接符

2.表达式求和运算符

3.数字取正运算符

第3点不常用,他的意思是表示数学里的正号。

var n = 1;
alert(+n);//表示+(1),其结果还是1。可与alert(-n),进行比较,这里的结果是-1

这三种情况中,1、2两点最容易出现二义性问题。因为这两种处理运算处理方式依赖与数据类型,而无法从运算符上进行判断。如:

c = a + b;

是根本无法知道他真实的含义是在求和还是在做字符串连接。

由于这种二义性的存在会出现一些问题。浏览器中,由于DOM模型的许多值看起来是数字,但实际上确实字符串。因此试图做加法运算时,实际却变成了字符串连接。

<img id = "testImg" style="border: 1 solid red" />
<script>
alert(testImg.style.borderWidth + 10);//1px10
</script>

另外,还有一条关于加号运算符的规则:如果表达式中存在字符串,则优先按字符串连接进行运算。

alert("123"+456);//123456
alert(123+"456");//123456

二、逗号“,”的二义性

先看下面几个示例,分析其表达的含义:

//示例1
a=(1,2,3);

//示例2
a=1,2,3;

//示例3
a=[1,2,(3,4,5),6];

//示例4
var a = 1,2,3;

示例1中,逗号被作为连续运算符使用,连续运算符(也叫逗号表达式)的意义是返回最后一个表达式的值,所以示例1的效果是“变量a赋值为3”。

示例2整个表达式为一个逗号表达式,因此整个表达式的值为最后一个表达式的值3,而变量a被赋值为1.

示例3中的逗号有两中含义(3,4,5)中的逗号表示连续运算符,而在1,2中则表示数组声明时的语法分隔符,因此示例3为将a声明为一个[1,2,5,6]的数组。

示例4并不会像示例2一样正常执行。因为这里的逗号被解释成了语句var声明时用来分隔多个变量的语法分隔符(var a, b,c),而数字2,3为不合法的语法声明,因此会在解释期就提示出错。

三、方括号“[]”的二义性

//示例1
a = [ [1][1] ];

这个奇怪的语句并没有语法错误,尽管我们几乎不能理解,但JavaScript解释器可以理解。为了弄清这个问题,必须了解方括号的作用:

1.用于声明数组直接量。

2.存取数组下标的运算符。

3.对象成员存取。

因此第一个"[1]"被理解成了一个数组的直接量,它只有一个元素。接下来,由于他是对象,所以第二个“[1]”就被理解为取下标为1的元素,很显然,这个元素还没有声明。

因此“[1][1]”的结果为undefined,而a就变成了a =[undefined],只有一个元素的数组,该元素为undefined.

下面再来看一个稍微复杂一点的例子:

var a = [ [‘a‘,1,2][‘b‘,3,4] ];

[‘a‘,1,2]仍然是一个数组的直接量,但[‘b‘,3,4]怎么解释呢?

首先要了解‘b‘,3,4被解释成为了一个逗号表达式,而他的值为4,因此[4]表示数组成员的存取,后面的过程就与上一个示例一样了。

时间: 2024-10-09 00:34:20

JavaScript语言精髓(1)之语法概要拾遗(转)的相关文章

试读《JavaScript语言精髓与编程实践》

有幸看到iteye的活动,有幸读到<JavaScript语言精髓与编程实践_第2版>的试读版本,希望更有幸能完整的读到此书. 说来读这本书的冲动,来得很诡异,写一篇读后感,赢一本书,其实奖励并不大,依靠纯粹的物质奖励,很显然,不会强烈的促使我去读这本书.而原因在于,一方面对javascript的极大兴趣,另一方面之前已经拜读过如<javascript高级程序设计><高性能javascript><javascript设计模式>等书,那我就有了要看看这本书都写了

《javascript语言精髓》笔记

做B\S项目已有一年多,自己是做后台出来的,对写js方面可能也沿用了以前的思路,想想毕竟也是OO语言嘛.然而,从上个项目吃的一些苦头,让我决心静下心来把js的书看看.这本<javascript语言精粹>是别人推荐给我的,之所以选择这本书,是因为我深知代码质量的重要性(想想自己以前写的代码,真想回去重写),代码写的越多,我就越想用更简洁的代码来实现功能,而这当然需要更深入的取理解一下js的设计模式和原理性的东西.很多人说js简单,是因为对这门语言不是很了解,也可以用它来工作,觉得就是一般的OO语

javascript语言精髓笔记

javascript是一门浏览器语言,对于后台攻城湿们.则是这样对其定义的 1. js是一门前端语言,因为js通常是web中的view部分,用来渲染最终呈现给用户的页面. 2. js是一门弱类型语言和解释性语言,没有使用编译器(编译器会检查语法错误,同样性质的比如php,ruby,python等.当然,不能说完全没有编译过程,只是不是严格意义上的编译),因为编译的目的最终应该是生成可执行的代码,而不是中间结果. 本文将关注两个方面 1.js重要概念 2.js小tips  主要关注容易被忽略的小问

(转)JavaScript二:JavaScript语言的基本语法要求

摘自:http://blog.csdn.net/erlian1992 要学习好JavaScript,首先我们要懂JavaScript语言的一些基本语法要求: 一,区分大小写 JavaScript语言区分字符大小写,两个字符串相同大小写不同,被认为是不同的字符串.JavaScript语言的关键字也区分大小写,按语法要求应小写. 二,书写格式 JavaScript语言忽略语句间空白,即语句间的空格,空行,缩进等.为了提高程序的可读性,应当使用这些格式,使程序更加清晰,可读性更高. 三,注释语句 为了

javascript语言中的毒瘤(上)

javascript语言中的毒瘤(上) 最近翻了<javascript语言精髓>,对js有了更进一步的了解,特别是js的糟糕特性,下面,结合书中的要点,给大家分享一下js的几个糟糕特性. 全局变量 全局变量实在所有作用域均可以访问的变量,在一些小型项目中全局变量给我们获取和使用函数,数据等提供了灵活,便捷:但是随着程序的越来越庞大,全局变量就变得越来越难维护:(因为一个变量可能会在很多地方被修改,还有可能被覆盖),一旦出现问题也很难定位和调试. Js的问题不仅在于它容许使用全局变量,而且在于它

JavaScript语言精粹pdf

内容简介  · · · · · · 本书通过对JavaScript语言的分析,甄别出好的和坏的特性,从而提取出相对这门语言的整体而言具有更好的可靠性.可读性和可维护性的JavaScript的子集,以便你能用它创建真正可扩展的和高效的代码. 雅虎资深JavaScript架构师Douglas Crockford倾力之作. 向读者介绍如何运用JavaScript创建真正可扩展的和高效的代码. 作者简介  · · · · · · Douglas Crockford是一名来自Yahoo!的资深JavaSc

JavaScript语言精粹 笔记01

内容比较简单,只是从头梳理一下JS的知识 语法空白标识符数字字符串语句 对象对象字面量检索更新引用原型反射枚举删除减少全局变量污染  语法 1 空白 空白可能表现为格式化字符或注释的形式.空白通常没有意义,但是偶尔必须用它来分割字符序列,否则它们就会被合并成一个单一的符号.例如: var that = this; var 和that之间的空格是不能去掉的,其他的空格都可以被移除. JS提供两种注释: /* */ // 建议使用//,因为/* */中要注释的内容可能包括字符 */ 而报错,例如:

第一章:Javascript语言核心

本节是javascript语言的一个快速预览,也是本书的第一部分快速预览. 本章之后,我们将主要关注javascript的基础知识.第二章我们讲解javascript的注释,分号和unicode字符集:第三章会更有意思,主要讲解javascript的变量和赋值 这里有一些实例代码说明前两章的重点内容. <script type="text/javascript"> //双斜杠之后之后的内容都于属于注释 //仔细阅读这里的注释,它将会对javascript代码做解释 // 变

javascript中正则表达式的基础语法

× 目录 [1]定义[2]特点[3]元字符[4]转义字符[5]字符组[6]量词[7]括号[8]选择[9]断言[10]模式[11]优先级[12]局限性 前面的话 正则表达式在人们的印象中可能是一堆无法理解的字符,但就是这些符号却实现了字符串的高效操作.通常的情况是,问题本身并不复杂,但没有正则表达式就成了大问题.javascript中的正则表达式作为相当重要的知识,本文将介绍正则表达式的基础语法 定义 正则表达式(Regular Expression)是一门简单语言的语法规范,是强大.便捷.高效的