亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Javascript核心讀書有感之表達(dá)式和運(yùn)算符

 更新時(shí)間:2015年02月11日 10:13:44   投稿:hebedich  
這篇文章主要介紹了Javascript核心讀書有感之表達(dá)式和運(yùn)算符,十分詳細(xì),需要的朋友可以參考下

表達(dá)式是javascript中的一個(gè)短語(yǔ),javascript解釋器會(huì)將其計(jì)算出一個(gè)結(jié)果。程序中常用量是最簡(jiǎn)單的一類表達(dá)式就是變量。變量名也是一種簡(jiǎn)單的表達(dá)式,它的值就是賦值給變量的值。

復(fù)雜的表達(dá)式是由簡(jiǎn)單的表達(dá)式組成的。比如數(shù)組訪問(wèn)表達(dá)式是由一個(gè)表示數(shù)組的表達(dá)式,方括號(hào)、一個(gè)整數(shù)表達(dá)式構(gòu)成。它們所組成新的表達(dá)式運(yùn)算結(jié)果是該數(shù)組特定位置的元素值。同樣的函

數(shù)調(diào)用表達(dá)式由一個(gè)表示函數(shù)對(duì)象的表達(dá)式和0個(gè)多個(gè)參數(shù)表達(dá)式構(gòu)成。將簡(jiǎn)單表達(dá)式組成復(fù)雜表達(dá)式最常用的方法就是運(yùn)算符。

本章(本文)將講解所有javascript運(yùn)算符。同時(shí)也講解不涉及運(yùn)算符的表達(dá)式(比如訪問(wèn)數(shù)組元素和函數(shù)調(diào)用),其語(yǔ)法和編程風(fēng)格和c語(yǔ)言都很相似。

1.元素表達(dá)式

最簡(jiǎn)單的表達(dá)式是“原始表達(dá)式”,原始表達(dá)式是表達(dá)式的最小的單位--它們不包含其他表達(dá)式。javascript中的原始表達(dá)式包含常量或直接量。關(guān)鍵字和變量。
直接量是直接在程序中出現(xiàn)的常數(shù)值。它們看起來(lái)像:

復(fù)制代碼 代碼如下:

           1.23 //數(shù)字直接量
            "hello" //字符串直接量
            /pattern/ //正則表達(dá)式直接量

javascript中的一些保留字構(gòu)成了原始表達(dá)式

復(fù)制代碼 代碼如下:

            true //布爾值:真
             false //假
             null //返回一個(gè)值:空
             this //返回"當(dāng)前"對(duì)象

通過(guò)第三章的學(xué)習(xí),和其它關(guān)鍵字不同,this并不是一個(gè)常量,他在程序的不同地方返回的值也不相同。this關(guān)鍵字經(jīng)常在面向?qū)ο缶幊讨谐霈F(xiàn)。this返回方格方法的對(duì)象。
最后,第三種原始表達(dá)式是變量

復(fù)制代碼 代碼如下:

    i //返回變量i的值
    sum //返回sum的值
    undefined //是全局變量,和null不同,它不是一個(gè)關(guān)鍵字

2.對(duì)象和數(shù)組的初始化表達(dá)式。

對(duì)象和數(shù)組初始化實(shí)際上是新創(chuàng)建的對(duì)象和數(shù)組,這些初始化的表達(dá)式有時(shí)候叫做“對(duì)象直接量”和“數(shù)組直接量”。然而和布爾直接量不同,他們不是原始表達(dá)式,因?yàn)樗麄兯某蓡T或者元素都子表達(dá)式。

數(shù)組的初始化表達(dá)式語(yǔ)法非常簡(jiǎn)單,我們以下開(kāi)始

數(shù)組的初始化表達(dá)式是通過(guò)一對(duì)方括號(hào)和其內(nèi)由逗號(hào)隔開(kāi)的列表構(gòu)成的,初始化結(jié)果是一個(gè)新創(chuàng)建的數(shù)組。數(shù)組的元素是逗號(hào)分隔表達(dá)式的值。

[] //一個(gè)空數(shù)組;[]內(nèi)留空即表示該數(shù)組沒(méi)有任何元素
[1+2,3+4] //有兩個(gè)元素的數(shù)組,第一個(gè)3,第二個(gè)是7
數(shù)組初始化表達(dá)式中的元素初始化表達(dá)式可以是數(shù)組初始化表達(dá)式。也就是說(shuō)表達(dá)式是可以嵌套的

復(fù)制代碼 代碼如下:

var mat = [[1,2,3],[4,5,6],[7,8,9]];

數(shù)組直接量中列表之間的元素可以省略,空位就會(huì)填充undefined.例如下面:

復(fù)制代碼 代碼如下:

var a=[1,,,,5]

其中4個(gè)元素是undefined.數(shù)組直接量的結(jié)尾處留下逗號(hào),這時(shí)不會(huì)創(chuàng)建一個(gè)新的值為undefined的元素。

對(duì)象初始化表達(dá)式和數(shù)組初始化表達(dá)式非常相似,只是方括號(hào)被花括號(hào)代替。并每個(gè)字表達(dá)式包含一個(gè)屬性名和非冒號(hào)作為前綴。

復(fù)制代碼 代碼如下:

var p = {x: 2.1,y: -3} //一個(gè)擁有兩個(gè)屬性成員的對(duì)象
            var q = {}; //空對(duì)象
            q.x=2.1;q.y=-3;  //q的屬性成員和p的一樣

對(duì)象直接量也可以嵌套,比如

復(fù)制代碼 代碼如下:

var anh = {left:{x:2,y:3},
                  right:{x:4,y:5}}

javascript在計(jì)算對(duì)象初始化表達(dá)式的值時(shí)候,對(duì)象表達(dá)式都會(huì)各自計(jì)算一次,并且他們不必包含常數(shù)值:它們可以是任意javascript表達(dá)式。同樣,對(duì)象直接量中屬性的名稱可以是字符串而不是標(biāo)識(shí)符。(在在那行只能使用保留字或一些非法標(biāo)識(shí)符作為屬性名的時(shí)候非常有用)

復(fù)制代碼 代碼如下:

            var side = 1;
            var square = {"left":{x:p.x,y:p.y},
            'right':{x:p.x+side,y:p.y+side}}

第6 7章還會(huì)再次討論對(duì)象和數(shù)組的初始化表達(dá)式。

3.函數(shù)表達(dá)式

函數(shù)定義表達(dá)式定義一個(gè)javascript函數(shù)。表達(dá)式的值是這個(gè)新定義的函數(shù)。從某種意義上將,函數(shù)定義表達(dá)式可以成為函數(shù)直接量,函數(shù)表達(dá)式可稱為“函數(shù)直接量”,畢竟對(duì)象初始化表達(dá)式也稱為“對(duì)象直接量”。一個(gè)典型的函數(shù)定義表達(dá)式包含關(guān)鍵字function,其后是一對(duì)圓括號(hào),括號(hào)以內(nèi)是逗號(hào)分隔的列表,列表包含0或多個(gè)標(biāo)識(shí)符(參數(shù)名)。然后跟隨花括號(hào)包裹的javascript代碼段(函數(shù)體).

var square = function(x){ return x*x};
函數(shù)定義表達(dá)式同樣可以包含函數(shù)的名字。函數(shù)也可以通過(guò)函數(shù)語(yǔ)句來(lái)定義,而不是函數(shù)表達(dá)式。更多內(nèi)容會(huì)在第八章描述。

4.屬性訪問(wèn)表達(dá)式

屬性訪問(wèn)表達(dá)式運(yùn)算得到一個(gè)對(duì)象或者一個(gè)數(shù)組元素的值。javascript為屬性訪問(wèn)定義了兩種方法。

復(fù)制代碼 代碼如下:

        expression . indentifier
        expression [expression]

第一種寫法是一個(gè)表達(dá)式后跟隨一個(gè)句點(diǎn)和標(biāo)識(shí)符。表達(dá)式指定對(duì)象,標(biāo)識(shí)符則指定要訪問(wèn)的屬性明川。
第二章寫法是使用方括號(hào),方括號(hào)內(nèi)是一個(gè)表達(dá)式(這種方法適用于對(duì)象和數(shù)組)。第二個(gè)表達(dá)式指定要訪問(wèn)的屬性的明川或者代表要訪問(wèn)數(shù)組元素的索引。這里有一些具體的例子

復(fù)制代碼 代碼如下:

    o.x //=>1表達(dá)式o的x屬性
        o.y.z //=>3 表達(dá)式o.y的z屬性
        o.["x"] //=>1的對(duì)象o的x屬性
        a[1]  //=>4 表達(dá)式a索引為1的元素
        a[2]["1"]//=>6 表達(dá)式a[2]中索引為1的元素
        a[0].x //=>1: 表達(dá)式a[0]的x屬性

不管使用哪種形式的屬性訪問(wèn)表達(dá)式,在"."和"["之前的表達(dá)式總會(huì)首先計(jì)算。如果計(jì)算結(jié)果為null或者undefined,表達(dá)式會(huì)拋出類型錯(cuò)誤異常,因?yàn)檫@兩個(gè)值都不能包含任意屬性。如果運(yùn)算結(jié)果不是對(duì)象或數(shù)組,javascript會(huì)將其轉(zhuǎn)換為對(duì)象(3章6節(jié)內(nèi)容)

雖然.identifier的寫法更加簡(jiǎn)單,但需要注意的是,這種方式只適用于要訪問(wèn)的屬性名稱是合法的標(biāo)識(shí)符。并且需要知道要訪問(wèn)的屬性名字。如果屬性名稱是一個(gè)保留字或者包含空格和標(biāo)點(diǎn)符號(hào),是一個(gè)數(shù)字(對(duì)于數(shù)組來(lái)說(shuō)),則必須使用方括號(hào)的寫法。當(dāng)屬性名是通過(guò)運(yùn)算符得出的值而不是固定值的時(shí)候,這時(shí)候必須使用方括號(hào)的寫法。(6章2節(jié)1小節(jié))

5.調(diào)運(yùn)表達(dá)式

javascript中的調(diào)用表達(dá)式(invocation expression)是一種調(diào)用(或者執(zhí)行)函數(shù)或方法的語(yǔ)法表示。它以一個(gè)函數(shù)表達(dá)式開(kāi)始,這個(gè)函數(shù)表達(dá)式指代了要調(diào)用的函數(shù)。函數(shù)表達(dá)式后跟隨一對(duì)圓括號(hào),括號(hào)內(nèi)是一個(gè)以逗號(hào)隔開(kāi)的參數(shù)列表。參數(shù)可以有0個(gè)也可以有多個(gè)。

            f(0) //f是一個(gè)函數(shù)表達(dá)式:0是一個(gè)參數(shù)表達(dá)式。
            Math.max(x,y,z)  //Math.max是一個(gè)函數(shù);x,y和z是參數(shù)
            a.sort() //a.sort()是一個(gè)函數(shù),它沒(méi)有參數(shù)。
當(dāng)調(diào)用表達(dá)式進(jìn)行求值的時(shí)候,首先計(jì)算函數(shù)表達(dá)式,然后計(jì)算參數(shù)表達(dá)式,得到一組參數(shù)值。如果函數(shù)表達(dá)式的值不是一個(gè)可調(diào)用的對(duì)象,則拋出一個(gè)類型錯(cuò)誤異常.然后參數(shù)的值依次被賦值給形參,這些形參是定義函數(shù)時(shí)定義的。接下來(lái)執(zhí)行函數(shù)體。如果函數(shù)使用return語(yǔ)句給出一個(gè)返回值,那么這個(gè)返回值就是整個(gè)調(diào)用表達(dá)式的值。否則,調(diào)用表達(dá)式的值就是undefined.函數(shù)調(diào)用--包括形參表達(dá)式的個(gè)數(shù)和函數(shù)定義中實(shí)參的個(gè)數(shù)不匹配的時(shí)候運(yùn)行的情況--的細(xì)節(jié)將會(huì)在第八章詳細(xì)說(shuō)明。

任何一個(gè)調(diào)用表達(dá)式都包含一對(duì)圓括號(hào)和左圓括號(hào)之前的表達(dá)式,如果這個(gè)表達(dá)式是一個(gè)屬性訪問(wèn)表達(dá)式,那么這個(gè)調(diào)用叫做“方法調(diào)用”(method invication)。在方法調(diào)用中執(zhí)行函數(shù)體的時(shí)候,作為屬性訪問(wèn)主體的對(duì)象和數(shù)組便是其調(diào)用方法內(nèi)this的指向。這種特性使得在面向?qū)ο缶幊痰姆独校瘮?shù)(其OO名稱為“方法”)可調(diào)用其宿主對(duì)象(第9章會(huì)有更多相關(guān)內(nèi)容)。

6.對(duì)象創(chuàng)建表達(dá)式

對(duì)象創(chuàng)建表達(dá)式(object creation expression)創(chuàng)建一個(gè)對(duì)象并調(diào)用一個(gè)函數(shù)(構(gòu)造函數(shù))來(lái)初始化對(duì)象的屬性。對(duì)象創(chuàng)建表達(dá)式和函數(shù)調(diào)用表達(dá)式非常類似,只是對(duì)象創(chuàng)建表達(dá)式之前多了一個(gè)關(guān)鍵字new:

        new Object()
        new Point(2,3)
如果對(duì)象創(chuàng)建表達(dá)式不需要傳入任何參數(shù)給構(gòu)造函數(shù)的話,那么這對(duì)圓括號(hào)是可以省略掉的,更多構(gòu)造函數(shù)的細(xì)節(jié)將在9章說(shuō)明

         new Object
         new Point

7.運(yùn)算符概述

javascript中的運(yùn)算符用于算表表達(dá)式, 比較表達(dá)式, 邏輯表達(dá)式 ,賦值表達(dá)式等
需要注意的是大多運(yùn)算符都是標(biāo)點(diǎn)符號(hào)來(lái)表示的,比如delete和instanceof.無(wú)論是關(guān)鍵字運(yùn)算符還是符號(hào)運(yùn)算符,所表示的運(yùn)算符一樣都是正規(guī)運(yùn)算符,他們的語(yǔ)法都非常言簡(jiǎn)意賅。
下標(biāo)運(yùn)算符的優(yōu)先級(jí)來(lái)排序的,前邊的運(yùn)算符優(yōu)先級(jí)高于后邊的運(yùn)算符優(yōu)先級(jí)。被水平華豐隔開(kāi)的運(yùn)算符具有不同的優(yōu)先級(jí)。
A表示運(yùn)算符的結(jié)合性。
L從左至右或者R(從右至左)
標(biāo)題N的列表表示操作數(shù)的個(gè)數(shù)。
類型表示期望的操作數(shù)的類型,以及運(yùn)算符的結(jié)果類型(在"→"符號(hào)之后)

運(yùn)算符 操作 A N 類型
++ 前/后增量 R 1 lval→num
-- 前后減量 R 1 lval→num
- 求反 R 1 num→num
+ 轉(zhuǎn)換為數(shù)字 R 1 num→num
~ 按位求反 R 1 int→int
! 邏輯非 R 1 bool→bool
delete 刪除屬性 R 1 lval→bool
typeof 檢測(cè)操作類型 R 1 any→Str
void 返回undefined值 R 1 any→undef
* 、/、% 乘 除 求余 L 2 num,num→num
+、- 加,減 L 2 num,num→num
+ 字符串連接 L 2 str,str→str
<< 左移位 L 2 int,int→int
>> 右移位 L 2 int,int→int
>>> 無(wú)符號(hào)右移

L

2 int,int→int
<,<=,>,>= 比較數(shù)字順序 L 2 num,num→bool
<,<=,>,>= 比較在字母中的順序 L 2 str,str→bool
instanceof 測(cè)試對(duì)象類 L 2 obj,func→bool
in 測(cè)試屬性是否存在 L 2 str,obj→bool
== 判斷相等 L 2 any,any→bool
!= 判斷不等 L 2 any,any→bool
=== 判斷恒等 L 2 any,any→bool
!== 判斷非恒等 L 2 any,any→bool
& 按位與 L 2 int,int→int
^ 按位異或 L 2 int,int→int
| 按位或 L 2 int,int→int
&& 邏輯與 L 2 any,any→any
|| 邏輯或 L 2 any,any→any
?: 條件運(yùn)算符 R 3 bool,any,any→any
= 變量賦值或?qū)ο髮傩再x值 R 2 lval,any→any

*= /= %= += -= &=

^= |= <<= >>= >>>=

運(yùn)算且賦值 R 2 lval,any→any
,

忽略第一個(gè)操作數(shù),

返回第二個(gè)操作數(shù)。

L 2 any,any→any

i.操作數(shù)的個(gè)數(shù)

運(yùn)算符可以通過(guò)操作數(shù)的個(gè)數(shù)進(jìn)行分類。

javascript中的大多數(shù)運(yùn)算符是二元運(yùn)算符,將兩個(gè)表達(dá)式合并成一個(gè)稍微復(fù)雜的表達(dá)式。
javascript也支持一些一元運(yùn)算符,它們將一個(gè)表達(dá)式轉(zhuǎn)換為另一個(gè)稍微復(fù)雜的表達(dá)式。表達(dá)式-x中的"-"運(yùn)算符就是一個(gè)一元運(yùn)算符。是將x求負(fù)值。
javascript支持一個(gè)三元運(yùn)算符:條件判斷運(yùn)算符“?:”,它將三個(gè)表達(dá)式合并為一個(gè)表達(dá)式

ii.操作數(shù)類型和結(jié)果類型

一些運(yùn)算符可以用于任何數(shù)據(jù)類型,但仍然希望它們操作指定的類型的數(shù)據(jù)。

iii.左值

在表中的賦值運(yùn)算符和其它少數(shù)運(yùn)算符期望它們的操作數(shù)lval類型,左值是一個(gè)古老的術(shù)語(yǔ)。它是指“表達(dá)式只能出現(xiàn)在賦值運(yùn)算符的左側(cè)”。javascript中,變量、對(duì)象屬性和數(shù)組元素均是左值。ECMAScript規(guī)范允許范圍內(nèi)置函數(shù)返回一個(gè)左值,但定義的函數(shù)則不能返回左值。

iiii.運(yùn)算符的優(yōu)先級(jí)

在上表中,所示的運(yùn)算符是按照優(yōu)先級(jí)從高到低排序的,每個(gè)水平分隔線內(nèi)一組運(yùn)算符有相同的優(yōu)先級(jí)。運(yùn)算符優(yōu)先級(jí)優(yōu)先控制著運(yùn)算符的執(zhí)行順序。運(yùn)算符高的(表頂)的執(zhí)行總是高于優(yōu)先級(jí)低的(表格的底部)運(yùn)算符。

看如下表達(dá)式

w=x+y*z;
乘法運(yùn)算符“*”比加法“+”具有更高的優(yōu)先級(jí),所以乘法先執(zhí)行。然后,由于賦值運(yùn)算符“=”具有最低優(yōu)先級(jí)。因此賦值操作是在右側(cè)的表達(dá)式計(jì)算出結(jié)果后進(jìn)行的。

運(yùn)算符的優(yōu)先級(jí)可以使用園括號(hào)來(lái)從寫。以上表達(dá)式可以這樣寫。

    w = (x + y) * z;
需要注意的是,屬性訪問(wèn)表達(dá)式和調(diào)用表達(dá)式的優(yōu)先級(jí)要比表中的所有運(yùn)算符都要高。

    typeof my.Function[x](y)
盡管typeof是優(yōu)先級(jí)最高的運(yùn)算符之一,但typeof也是在兩次屬性訪問(wèn)和函數(shù)調(diào)用后執(zhí)行的。

事實(shí)上,如果你真的不確定你所使用的運(yùn)算符優(yōu)先級(jí),最簡(jiǎn)單的方法就是使用園括號(hào)來(lái)強(qiáng)行指定運(yùn)算次序。有些重要的規(guī)則則要熟記:乘法和除法高于加減法,賦值運(yùn)算的優(yōu)先級(jí)非常低,通常是最后執(zhí)行的。

iiiiii.運(yùn)算符的結(jié)合性

在本節(jié)表中,標(biāo)題為A的列說(shuō)明了運(yùn)算符的結(jié)核性。L指從左至右結(jié)合,R指從右至左結(jié)合。結(jié)核性指定了在多個(gè)具有同樣優(yōu)先級(jí)的運(yùn)算符表達(dá)式中的運(yùn)算順序。

例如,減法運(yùn)算按照由左到右的執(zhí)行結(jié)合性。

復(fù)制代碼 代碼如下:

w = x - y - z

和這段代碼一樣:

復(fù)制代碼 代碼如下:

w = ((x - y) - z)

反過(guò)來(lái)講,下面這個(gè)表達(dá)式:

復(fù)制代碼 代碼如下:

x = ~-y;
w = x = y = z;
q=a?b:c?d:e?f:g;

和這段代碼一模一樣

復(fù)制代碼 代碼如下:

x=~(-y);
w=(x=(y=z));
q=a?b:(c?d:(e?f:g))

因?yàn)橐辉僮鞣?、賦值和三元條件運(yùn)算符都具有從右至左的結(jié)合性。

iiiiiii.運(yùn)算順序

運(yùn)算符的優(yōu)先級(jí)和結(jié)合性規(guī)定了它們?cè)谫x值的運(yùn)算式中的運(yùn)算順序,但并沒(méi)有規(guī)定字表達(dá)式的計(jì)算過(guò)程中的運(yùn)算順序。javascript總是嚴(yán)格按照從左至右的順序計(jì)算表達(dá)式,例如:

在表達(dá)式 w=x+y*z 中,將首先計(jì)算表達(dá)式w,然后計(jì)算x、y和z,然后,y的值和z相乘,在加上x的值。最后將其表達(dá)式w所指代的變量或?qū)傩?。給表達(dá)式添加園括號(hào)將會(huì)改變乘法,加法和賦值運(yùn)算的關(guān)系。但從左至右的順序是不會(huì)改變的。

8.算術(shù)表達(dá)式

本節(jié)涵蓋了那些算術(shù)計(jì)算的運(yùn)算符、以及對(duì)操作數(shù)的算術(shù)操作。乘法、除法和減法運(yùn)算符非常簡(jiǎn)單。加法運(yùn)算單獨(dú)一節(jié),因?yàn)榧臃ㄟ\(yùn)算符可以操作字符串的連接,并且其類型轉(zhuǎn)換有些特殊。

基本的算術(shù)運(yùn)算符是*、/、%、+、-。除了+加法,其它的運(yùn)算符特別簡(jiǎn)單,只是在必要的時(shí)候操作符轉(zhuǎn)化為數(shù)字而已,然后求積、商、余(模)和差。所有那些無(wú)法轉(zhuǎn)換為數(shù)字的操作都將轉(zhuǎn)換為NaN值。如果操作數(shù)(或者轉(zhuǎn)換結(jié)果)是NaN值,算術(shù)運(yùn)算結(jié)果也是NaN

運(yùn)算符“/”用第二個(gè)操作數(shù)來(lái)除以第一個(gè)操作數(shù),如果你使用過(guò)那些區(qū)分整數(shù)型和浮點(diǎn)數(shù)型的編程語(yǔ)言。那么用一個(gè)整數(shù)除以一個(gè)整數(shù)時(shí),則希望得到的結(jié)果也是整數(shù)。在javascript中所有的數(shù)字都是浮點(diǎn)數(shù)型的,除法運(yùn)算的結(jié)果也是浮點(diǎn)型。比如5/2結(jié)果是2.5,而不是2。除數(shù)為0的運(yùn)算結(jié)果為正無(wú)窮大或負(fù)無(wú)窮大。而0/0的結(jié)果是NaN。所有這些運(yùn)算均不會(huì)報(bào)錯(cuò)。

運(yùn)算符“%”計(jì)算的是第一個(gè)操作數(shù)對(duì)第二個(gè)操作數(shù)的模,換句話說(shuō),就是第一個(gè)操作數(shù)除以第二個(gè)操作鼠的余數(shù)。結(jié)果的符號(hào)和第一個(gè)操作鼠(被除數(shù))符號(hào)保持一致。例如5%2的結(jié)果為1,-5%2為-1。

求余運(yùn)算符的操作數(shù)通常都是整數(shù),但也適用于浮點(diǎn)數(shù)。6.5%2.1結(jié)果是0.2。(0.19999999999999973)

i.“+”運(yùn)算符

二元加法運(yùn)算符“+”可以對(duì)兩個(gè)數(shù)字做加法,也可以做字符串連接操作:

復(fù)制代碼 代碼如下:

         1+2 //=> 3
        "hello" + "" + "there" // =>"hello there"
        "1"+"2" //=>"12"

當(dāng)兩個(gè)操作數(shù)都是數(shù)字或都是字符串的時(shí)候,計(jì)算結(jié)果是顯而易見(jiàn)的。然而對(duì)于其他情況來(lái)說(shuō),則要進(jìn)行一些必要的類型轉(zhuǎn)換。并且運(yùn)算符的行為依賴于類型的轉(zhuǎn)換的結(jié)果。從技術(shù)上來(lái)講,加法操作符的行為表現(xiàn)為:

如果一個(gè)操作數(shù)是對(duì)象,則對(duì)象會(huì)遵循對(duì)象到原始值的轉(zhuǎn)換規(guī)則為原始類值(參照3章8節(jié)3小節(jié))。日期對(duì)對(duì)象toString()方法執(zhí)行轉(zhuǎn)換,其他對(duì)象則通過(guò)valueOf()方法執(zhí)行轉(zhuǎn)換(如果valueOf()方法返回一個(gè)原始值的話)。由于多數(shù)對(duì)象都不具備可用的valueOf()方法,因此他們會(huì)通過(guò)toString()方法來(lái)執(zhí)行抓換
在進(jìn)行了對(duì)象到原始值的轉(zhuǎn)換后,如果其中一個(gè)操作鼠是字符串的話,另一個(gè)操作數(shù)也會(huì)轉(zhuǎn)換為字符串。然后進(jìn)行字符串連接。
否則,兩個(gè)操作數(shù)都將轉(zhuǎn)換為數(shù)字(或者NaN),然后進(jìn)行加法操作。
這里有一些例子

復(fù)制代碼 代碼如下:

            1 + 2 //=>3 加法
                "1" + "2" //=>"12" 字符串連接
            "1" + 2 //=>"12"數(shù)字轉(zhuǎn)換為字符串后進(jìn)行字符串連接
             1 + {} //=>"1[object object]":對(duì)象轉(zhuǎn)換為字符串后進(jìn)行字符串連接
            true + true //=>2 布爾值轉(zhuǎn)換為數(shù)字后做加法
             2 + null //=>2 null轉(zhuǎn)換為0后做加法
             2 + undefined //=>NaN undefined轉(zhuǎn)換為NaN做加法

最后,特別要注意的是。當(dāng)加號(hào)運(yùn)算符合字符串一起使用時(shí),要考慮加法對(duì)運(yùn)算順序的影響。也就是說(shuō),運(yùn)算結(jié)果是依賴于運(yùn)算符的運(yùn)算順序的,比如

復(fù)制代碼 代碼如下:

            1 + 2 + "bmice" //=> "3 bmice"
            1 + (2 + "bmice") => "12bmice"

ii.一元運(yùn)算符

一元運(yùn)算符作用于一個(gè)單獨(dú)的操作數(shù)。并產(chǎn)生一個(gè)新值。在javascript中,一元運(yùn)算符具有很高的優(yōu)先級(jí),而且都是右結(jié)合。本節(jié)講述一元運(yùn)算符(+,-,++和--),必要時(shí),他們將操作轉(zhuǎn)換為數(shù)字。需要注意的的是+ -是一元運(yùn)算符,也是二元運(yùn)算符、

一元加法+

          一元加法運(yùn)算符把操作數(shù)數(shù)轉(zhuǎn)換為數(shù)字(或者NaN),并且返回這個(gè)轉(zhuǎn)換后的數(shù)字。如果操作數(shù)本身就是數(shù)字,則直接返回這個(gè)數(shù)字。

一元減法-

           當(dāng)-號(hào)做一元運(yùn)算符時(shí),它會(huì)根據(jù)需要把操作數(shù)轉(zhuǎn)換為數(shù)字,然后改變運(yùn)算結(jié)果的符號(hào)、

遞增++

           遞增“++”運(yùn)算符對(duì)其操作數(shù)進(jìn)行增量(+1)的操作,操作數(shù)一個(gè)左值(變量、數(shù)組元素或者對(duì)象屬性)。運(yùn)算符將操作數(shù)轉(zhuǎn)換為數(shù)字。然后給數(shù)字加1、并將加1后的數(shù)值重新賦值給變量、數(shù)組元素或者對(duì)象屬性。

           遞增++ 運(yùn)算返回值依賴它對(duì)操作數(shù)的位置。

           當(dāng)操作符在操作數(shù)數(shù)之前,稱為“前增量”(pre-increment)運(yùn)算符,它對(duì)操作數(shù)進(jìn)行增量計(jì)算,并返回計(jì)算后的值。

           當(dāng)操作符在操作數(shù)之后,稱為"后增量"(post-increment)運(yùn)算符,它對(duì)操作數(shù)進(jìn)行增量計(jì)算,但返回為做增量計(jì)算的(unincremented)值。如

            var i = 1,j = ++i //i和j的值都是2
            var i = 1,j = i++; //i是2,j是1
需要注意的是,便打算++x并總和x=x+1完全一樣,“++”運(yùn)算符從不進(jìn)行字符串連接操作,它總會(huì)將操作數(shù)轉(zhuǎn)換為數(shù)字并增1.如果x是字符串“1”,++x的結(jié)果就是數(shù)字2,而x+1是字符串"11"

遞減和遞增的操作方式是同樣的,它把操作數(shù)轉(zhuǎn)換為數(shù)組,然后減1.

iii.位運(yùn)算符

位運(yùn)算符可以對(duì)數(shù)字表示的二進(jìn)制數(shù)據(jù)進(jìn)行更低層級(jí)的按位運(yùn)算。盡管它們不是傳統(tǒng)的純數(shù)學(xué)運(yùn)算,但這里也歸類為算術(shù)運(yùn)算符,因?yàn)樗麄冏饔糜跀?shù)值類型的操作并返回?cái)?shù)字。這些運(yùn)算符在javascript不常見(jiàn)。(此處不描述,詳情自行百度~-~)           

9.關(guān)系表達(dá)式

本節(jié)講述javascript的關(guān)系運(yùn)算符,關(guān)系運(yùn)算符用于測(cè)試兩個(gè)值之間中的關(guān)系(相等、小于或“是...的屬性”),根據(jù)關(guān)系是否存在而返回true和false.關(guān)系表達(dá)式總是返回一個(gè)布爾值,通常在if while或者for語(yǔ)句(第五章)中使用關(guān)系表達(dá)式,以控制程序的執(zhí)行流程。

接下來(lái)幾節(jié)會(huì)講述相等和不等運(yùn)算、比較運(yùn)算符和javascript中其它兩個(gè)關(guān)系符in和instanceof

i相等和不等運(yùn)算符

“==”和"==="運(yùn)算符用于比較兩個(gè)值是否相等,兩個(gè)運(yùn)算符允許任意類型的操作符。如果相等則返回true,否則返回false.“===”也稱為嚴(yán)格相等運(yùn)算符(有時(shí)稱為恒等運(yùn)算符),它用于檢測(cè)兩個(gè)操作數(shù)是否嚴(yán)格相等?!?=”運(yùn)算符稱作相等運(yùn)算符,它用來(lái)檢測(cè)兩個(gè)操作數(shù)是否相等,這里的相等定義寬松,可以允許進(jìn)行類型轉(zhuǎn)換。

javascript支持“=”,“==”,“===”運(yùn)算符,你應(yīng)當(dāng)理解(賦值,相等,恒等)運(yùn)算符之間的區(qū)別。并在編程中小心使用。為了減少混淆,應(yīng)該把“=”稱作“得到或賦值”,把“==”稱作“相等”,把“===”稱作“嚴(yán)格相等”。

“!=”和“!==”運(yùn)算符規(guī)則是“==”,“===”運(yùn)算符的求反,“!”是布爾非運(yùn)算符,我們將“!=”,“!==”稱為不相等,不嚴(yán)格相等

javascript對(duì)象的比較是引用的比較,而不是值的比較。對(duì)象和本身是相等的,但和人和對(duì)象都不相等。如果兩個(gè)對(duì)象具有相同數(shù)量的屬性,相同的屬性名和值,它們依然是不相等的。相應(yīng)位置的數(shù)組元素是相等的兩個(gè)數(shù)組也是不相等的。

嚴(yán)格相等運(yùn)算符"==="首先計(jì)算操作數(shù)的值,然后比較這兩個(gè)值,比較過(guò)程沒(méi)有任何類型轉(zhuǎn)換。

如果兩個(gè)值類型不想同,則它們不相等
如果兩個(gè)值都是null或者undefined,則它們不相等
如果兩個(gè)值都是布爾值true或者false, 則它們相等
如果其中一個(gè)值是NaN,或者兩個(gè)值都是NaN ,則它們不相等,NaN和其它值都是不相等的,包括它本身。
如果兩個(gè)值為數(shù)字且相等,則它們相等。如果一個(gè)值為0,令一個(gè)值為-0,則它們同樣相等。
如果兩個(gè)值為字符串,并且所含對(duì)應(yīng)位上的16位數(shù)(參照3章2節(jié))完全相等,則它們相等。如果他們的長(zhǎng)度或內(nèi)容不同,則不相等。兩個(gè)字符串可能函數(shù)完全一樣并且所顯示出的字符也一樣,但具有不用編碼的16位值,javascript并不對(duì)Unicode進(jìn)行標(biāo)準(zhǔn)轉(zhuǎn)換,因此這樣的字符串通過(guò)"==="和"=="運(yùn)算符的比較結(jié)果也不相等。第三部分的String.localeCompare()提供了另外一種比較字符串的方法。
如果兩個(gè)引用值指向同一個(gè)對(duì)象,數(shù)組或函數(shù),則它們是相等的。如果指向不同的對(duì)象,則它們是不等的,盡管兩個(gè)對(duì)象有完全相同的屬性。
相等運(yùn)算符"=="和恒等運(yùn)算符相似,但相等運(yùn)算符比較并不嚴(yán)格。如果兩個(gè)數(shù)不是同一類型,那么相等運(yùn)算符會(huì)嘗試進(jìn)行一些類型轉(zhuǎn)換,然后進(jìn)行比較。

如果兩個(gè)操作類型相同,則和上文相等運(yùn)算符的比較規(guī)則一樣。如果嚴(yán)格相等,那么比較結(jié)果相等。如果他們不嚴(yán)格相等,則比較結(jié)果不相等。
如果兩個(gè)操作類型不同,“==”相等操作符也會(huì)認(rèn)為它們相等。檢測(cè)相等會(huì)遵循如下的規(guī)則和類型轉(zhuǎn)換:
   如果一個(gè)類型是null,令一個(gè)是undefined,則它們相等
   如果一個(gè)值是數(shù)字,另一個(gè)是字符串,先將字符串轉(zhuǎn)換為數(shù)字,然后使用轉(zhuǎn)換后的值進(jìn)行比較。
   如果一個(gè)值是true,則將其轉(zhuǎn)換為1再進(jìn)行比較,如果一個(gè)值是false,則轉(zhuǎn)換為0比較。
   如果一個(gè)值是對(duì)象,另一個(gè)值是數(shù)字或字符串,則使用3章8節(jié)3小節(jié)的方法的轉(zhuǎn)換規(guī)則將對(duì)象轉(zhuǎn)換為原始值,然后進(jìn)行比較。對(duì)象通過(guò)toString()方法或者valueOf()方法轉(zhuǎn)換為原始值。javascript語(yǔ)言核心的內(nèi)置類首先嘗試使用valueOf()再嘗試使用toString(),除了日期類,日期類只能通過(guò)toString()轉(zhuǎn)換。那些不是javascript 語(yǔ)言核心中的對(duì)象則通過(guò)實(shí)現(xiàn)中定義的方法轉(zhuǎn)換為原始值。
   其它不同類型之間的比較均不相等
這里有一個(gè)判斷相等的小例子

"1" == true
這個(gè)表達(dá)式的結(jié)果為true,這表明完全不同類型的值比較結(jié)果為相等。布爾值true首先轉(zhuǎn)換為數(shù)字1 ,然后再執(zhí)行比較。接下來(lái)字符串“1”也會(huì)轉(zhuǎn)換為數(shù)字1 ,因?yàn)閮蓚€(gè)數(shù)字的值相等,因此結(jié)果為true.

ii.比較運(yùn)算符

小于(<)

如果第一個(gè)操作數(shù)小于第二個(gè)操作數(shù),則“<”運(yùn)算結(jié)果我true,否則為false

小于等于(<=)

大于(>)

大于等于(>=)

....(不詳細(xì)介紹含義)

比較操作符的操作數(shù)可能是任意類型。然而只有數(shù)字和字符串才能真正執(zhí)行比較操作符,因此,那些不是數(shù)字和字符串的操作數(shù)都將進(jìn)行類型轉(zhuǎn)換。類型轉(zhuǎn)換規(guī)則如下:

如果操作數(shù)為對(duì)象,則按照3章8節(jié)3小節(jié)處鎖描述的轉(zhuǎn)換規(guī)則轉(zhuǎn)換為原始值:如果valueOf()返回一個(gè)原始值,那么直接使用這個(gè)原始值。否則使用toString() 的轉(zhuǎn)換結(jié)果進(jìn)行比較。
在對(duì)轉(zhuǎn)換為原始值之后,如果兩個(gè)操作數(shù)都是字符串,那么將依字母表的順序?qū)蓚€(gè)字符串進(jìn)行比較,這里提到的“字母表順序”是組成這兩個(gè)字符串的16位Unicode字符的索引順序。
在對(duì)象轉(zhuǎn)換為原始值之后,如果至少一個(gè)操作數(shù)不去是字符串,那么兩個(gè)操作數(shù)都將為數(shù)字進(jìn)行數(shù)值的比較。0和-0是相等的。Infinty壁其它任何數(shù)字都大(除了infinty本身),-infinty比任何數(shù)字都?。ǔ怂约罕旧?。)如果一個(gè)操作數(shù)(或轉(zhuǎn)換后)為NaN,那么比較符總是返回false
對(duì)于數(shù)字和字符串操作符來(lái)說(shuō),加號(hào)運(yùn)算符和比較運(yùn)算符的行為有所不同 ,前者更偏愛(ài)字符串,如果它的其中一個(gè)操作數(shù)是字符串的話,則進(jìn)行字符串連接操作。而比較運(yùn)算符則更偏愛(ài)數(shù)字,只有在兩個(gè)操作數(shù)都是字符串串的時(shí)候。才會(huì)進(jìn)行字符串的比較。

復(fù)制代碼 代碼如下:

            1 + 2 //=>3 加法,結(jié)果為3
            "1" + "2" //字符串連接,結(jié)果為"12"
            "1" + 2 //字符串連接,2轉(zhuǎn)換為"2",結(jié)果"12"
            11 < 3 //數(shù)字比較,結(jié)果true
            "11" < "3" //字符串比較,結(jié)果為true
            "11" < 3 //數(shù)字的比較,“11”轉(zhuǎn)換為11,結(jié)果為true
            "one" < 3 //數(shù)字比較,"one"轉(zhuǎn)換為NaN,結(jié)果為falase

最后需要注意的是,“<=”和“>=”運(yùn)算符在判斷相等的時(shí)候,并不依賴相等運(yùn)算符和和嚴(yán)格相等運(yùn)算比較規(guī)則。相反,小于等于運(yùn)算符芝是簡(jiǎn)單的“不大于”,大于等于運(yùn)算只是“不小于”。只有一個(gè)例外,的那個(gè)一個(gè)操作數(shù)(后轉(zhuǎn)換后)是NaN的時(shí)候,所有4個(gè)比較運(yùn)算符均會(huì)返回fasle.

iii.in運(yùn)算符

in運(yùn)算符希望它的左操作數(shù)是一個(gè)字符串或者可以轉(zhuǎn)換為字符串,希望它的右側(cè)是一個(gè)對(duì)象。如果右側(cè)的對(duì)象擁有一個(gè)名為左操作數(shù)值的屬性名,那么表達(dá)式返回true.例如

復(fù)制代碼 代碼如下:

var point = {
                    x: 1,
                    y: 1
                } //定義一個(gè)對(duì)象
                 "x" in point //=>true 對(duì)象有一個(gè)名為x的屬性
                "z" in point //=>false 對(duì)象無(wú)名為z的屬性
                "toString" in point // =>true 對(duì)象繼承了toString方法

            var data = [7, 8, 8]
            "0" in data //=>true 數(shù)組包含0
             1 in data //=>true 數(shù)字轉(zhuǎn)換為字符串
             3 in data //=>fase 沒(méi)有索引為3的元素

iiii.instanceof運(yùn)算符

instanceof運(yùn)算符希望左操作符為一個(gè)對(duì)象,右操作數(shù)標(biāo)示對(duì)象的類。如果左側(cè)的對(duì)象是右側(cè)類的實(shí)例,則表達(dá)式返回true;負(fù)責(zé)返回false.第9章將會(huì)講到。javascript對(duì)象的類是通過(guò)初始化他們的構(gòu)造函數(shù)的來(lái)定義的。這樣的話,instanceof的右操作數(shù)應(yīng)當(dāng)是一個(gè)函數(shù)。比如:

復(fù)制代碼 代碼如下:

            var d = new Date(); //構(gòu)造一個(gè)新對(duì)象
            d instanceof Date; //計(jì)算結(jié)果為true, d是Date() 創(chuàng)建的
            d instanceof Object //計(jì)算結(jié)果為true ,所有的對(duì)象都是Object的實(shí)例
             d instanceof Number //計(jì)算結(jié)果為 false,d不是一個(gè)Number對(duì)象
             var a = [1,2,3] //數(shù)組直接量創(chuàng)建數(shù)組
             a instanceof Array //計(jì)算結(jié)果true a為數(shù)組
             a instanceof Object //true 所有的數(shù)組都是對(duì)象
             a instanceof RegExp //fasle 數(shù)組不是正則表達(dá)式

需要注意的是,所有對(duì)象都是Object的實(shí)例。當(dāng)通過(guò)instanceof盤對(duì)一個(gè)對(duì)象是否為一個(gè)類的實(shí)例的時(shí)候,這個(gè)判斷也叫“父類”(superclass)的檢測(cè),如果instanceof的左側(cè)操作對(duì)象不是對(duì)象的話,instanceof返回false。如果右側(cè)操作不是函數(shù),則拋出類型錯(cuò)誤的異常。

為了理解instanceof運(yùn)算符是如何工作的,必須首先理解“原型類”(prototype chain),原型鏈作為javascript的繼承機(jī)制,將在6章2節(jié)2小節(jié)詳細(xì)描述。

為了計(jì)算表達(dá)式o instanceof f ,javascript筆仙首先計(jì)算f.prototyoe,然后在原型鏈中查詢o,如果找到,那么o是f(或者f的父類)的一個(gè)實(shí)例,那么返回true。反之false

10.邏輯表達(dá)式

邏輯運(yùn)算符"&&"、“||”、“!”是對(duì)操作進(jìn)行布爾算術(shù)運(yùn)算,經(jīng)常和關(guān)系運(yùn)算符一起配合使用,邏輯運(yùn)算符將多個(gè)關(guān)系表達(dá)式組合起來(lái)組成一個(gè)更復(fù)雜的表達(dá)式。

i.邏輯與

"&&"運(yùn)算符可以從三個(gè)不同的層次進(jìn)行理解。最簡(jiǎn)單一層理解是,當(dāng)操作數(shù)都是布爾值是,“&&”對(duì)兩個(gè)布爾值執(zhí)行布爾與(AND)操作,只有在第一個(gè)操作數(shù)和第二個(gè)操作數(shù)都是true的時(shí)候,它才返回true.如果其中有一個(gè)操作數(shù)為false.則它返回false.

"&&"長(zhǎng)用來(lái)連接兩個(gè)關(guān)系表達(dá)式

x == 0 && y == 0; //只有在x和y都是0時(shí),才返回true
關(guān)系表達(dá)式總是返回true或false,因此當(dāng)這樣使用的時(shí)候,“&&”本身也返回true或 false。關(guān)系運(yùn)算符的優(yōu)先級(jí)要比"&&"(和“||”)要高,因此類似這種表達(dá)式可以放心地書寫,而不用補(bǔ)充園括號(hào)。

"&&"操作數(shù)并不一定是布爾值,回想一下,有些值是可以當(dāng)做“真值”和“假值”的。(如3章3節(jié),假值是:false null undefined 0 -0 NaN和"",所有和其它的值包括所有的對(duì)象都是真值)。對(duì)“&&”第二層理解是,“&&”是可以對(duì)真值和假值進(jìn)行布爾與(AND)操作。如果兩個(gè)操作數(shù)都是真值的,則那么返回一個(gè)真值;否則,至少一個(gè)操作數(shù)是假值的。javascript中在任何使用布爾值的地方的時(shí)候,表達(dá)式語(yǔ)句都會(huì)將其當(dāng)做真值或假值來(lái)對(duì)待,因此實(shí)際上“&&”并不總是返回true和false.但也并無(wú)大礙。

需要注意的是,上文提到了運(yùn)算符返回“真值”和“假值”,但并沒(méi)說(shuō)說(shuō)明這個(gè)“真值”或者“假值”到底是什么值,為此我們深入討論對(duì)“&&”第三層的理解。運(yùn)算符首先計(jì)算左操作數(shù)的值,即首先計(jì)算“&&”左側(cè)的表達(dá)式,如果計(jì)算結(jié)果是假值,那么整個(gè)表達(dá)式的結(jié)果一定是假值,因此“&&”這時(shí)簡(jiǎn)單的返回左操作的值,而并不會(huì)對(duì)右邊的操作數(shù)進(jìn)行計(jì)算。

復(fù)制代碼 代碼如下:

    var o = {
                x: 1
            };
            var p = null;
            o && o.x; //=>1 : 1:0是真值,因此返回值是o.x
            p && p.x //= null :p是假值,因此將其返回,而并不計(jì)算p.x

這對(duì)于理解“&&”可能不計(jì)算右操作數(shù)的情況至關(guān)重要,在上述代碼中,變量P的值是null,而如果計(jì)算p.x的話則會(huì)拋出一個(gè)異常錯(cuò)誤,因此,只有p為真值(不能是null或undefined)的情況下才計(jì)算p.x

"&&"的行為有時(shí)候被稱為“短路”(short circuiting),我們經(jīng)常能看到很多代碼利用了這一也行來(lái)有條件的執(zhí)行代碼。例如下面的兩條代碼是等價(jià)的

復(fù)制代碼 代碼如下:

             if (a == b) stop(); //只有a==b時(shí)才能調(diào)運(yùn)stop()
            (a == b) && stop(); //同上

一般來(lái)講,當(dāng)“&&”右側(cè)的表達(dá)式具有副作用的時(shí)候(賦值,遞增,遞減和函數(shù)調(diào)用表達(dá)式)要格外小心。因?yàn)檫@些帶有副作用的表達(dá)式的執(zhí)行時(shí)候,依賴于左操作鼠的計(jì)算結(jié)果。

盡管“&&”可以按照第二層和第三層的理解進(jìn)行一些復(fù)雜的表達(dá)式運(yùn)算,但大多數(shù)的情況下,“&&”僅用來(lái)對(duì)真值和假值的做布爾計(jì)算。

ii.邏輯或(||)

"||"運(yùn)算符對(duì)兩個(gè)操作數(shù)做布爾或(OR)運(yùn)算。如果其中一個(gè)為真值,則返回真值,兩個(gè)操作數(shù)都為假值,返回假值。

盡管“||”運(yùn)算符大多情況下只是做簡(jiǎn)單的布爾或(OR)運(yùn)算,和“&&”一樣,也具備一些更復(fù)雜的行為,它首先計(jì)算第一個(gè)操作數(shù)的值,也就是說(shuō)回首先計(jì)算左側(cè)的表達(dá)式,如果計(jì)算結(jié)果為真,則返回真值,否則,再計(jì)算第二個(gè)值。

和“&&”一樣,用于應(yīng)該避免右操作數(shù)包含一些具有副作用的表達(dá)式,除非你目地明確在右側(cè)使用帶副作用的表達(dá)式,而有可能不會(huì)計(jì)算右側(cè)的表達(dá)式。

這個(gè)運(yùn)算符最常用的方式是用來(lái)從一組備選的表達(dá)中選取第一個(gè)真值的表達(dá)式。

復(fù)制代碼 代碼如下:

        //如果max_width已經(jīng)定義了,則直接使用它。賦值在preferences對(duì)象中查找max_width
        //如果沒(méi)有定義它,則使用一個(gè)寫死的常量。
        var max =max_width || preferences.max_windth || 500;

這種貫用法通常在函數(shù)體內(nèi),用來(lái)給參數(shù)提供默認(rèn)值。

復(fù)制代碼 代碼如下:

          //將o成功的屬性復(fù)制到p中,并返回p
            function copy(o, p) {
                p = p || {}; //如果向參數(shù)p沒(méi)有傳入任何對(duì)象,則使用一個(gè)新創(chuàng)建對(duì)象。
                //函數(shù)體內(nèi)的主邏輯

iii.邏輯非(!)

"!"運(yùn)算符是一元運(yùn)算符,它放置在一個(gè)單獨(dú)操作數(shù)之前。它的目的是將操作數(shù)的布爾值求反。

和"&&"、"||"運(yùn)算符不同,“!”運(yùn)算符首先將其操作數(shù)轉(zhuǎn)換為布爾值(參考第三章的講訴規(guī)則),然后再對(duì)布爾值求反。也就是"!"總是返回true和 false。并且,可以通過(guò)使用兩次邏輯非運(yùn)算來(lái)得到一個(gè)值的布爾值:(!!x,參照第三章第八節(jié)第2小節(jié))

“!”具有很高的優(yōu)先級(jí),并且和操作數(shù)緊密的綁在一起,如果希望對(duì)p && q,則需要園括號(hào)!(p && q)。如下代碼:

復(fù)制代碼 代碼如下:

            !(p && q) === !p || !q
            !(p || q) === !p && !q

對(duì)于p和q取任何值,這兩個(gè)表達(dá)式永遠(yuǎn)成立。

11.賦值表達(dá)式

javascript使用"="運(yùn)算符給變量或者屬性來(lái)賦值,例如:

復(fù)制代碼 代碼如下:

             i = 0 //將變量i設(shè)置為0
             o.x = 1 //將對(duì)象o的屬性x 設(shè)置為1

“=”運(yùn)算符希望它的左操作數(shù)為一個(gè)左值:一個(gè)變量或者對(duì)象屬性(或數(shù)組元素),它的右操作鼠可以是任意的類型的任意值。賦值表達(dá)式的值就是右操作數(shù)的值。賦值表達(dá)式的副作用是,右操作數(shù)的值賦值給左側(cè)的變量或?qū)ο髮傩?。這樣的話,后續(xù)對(duì)這個(gè)變量和對(duì)象的屬性的引用都將得到這個(gè)值。

盡管賦值表達(dá)式的值非常簡(jiǎn)單,但有時(shí)候會(huì)看到一些復(fù)雜表達(dá)式包含賦值表達(dá)式的情況。例如:將賦值和檢測(cè)操作放在一個(gè)表達(dá)式中:

復(fù)制代碼 代碼如下:

(a = b) == 0

如果這樣的話,應(yīng)該清楚地知道"="和"=="區(qū)別!,需要注意的是,“=”有非常低的優(yōu)先級(jí),通常在一個(gè)較長(zhǎng)的表達(dá)式中用到一條賦值語(yǔ)句時(shí),需要補(bǔ)充園括號(hào)以保障正確的運(yùn)算順序。

賦值操作符的結(jié)合性是從右至左,也就是說(shuō),一個(gè)表達(dá)式中出現(xiàn)了多個(gè)賦值運(yùn)算符,運(yùn)算順序也從右至左,因此,可以通過(guò)以下方式對(duì)多個(gè)變量賦值。

復(fù)制代碼 代碼如下:

        i=j=k=0; //把三個(gè)變量初始化為0

帶操作的賦值運(yùn)算:

除了常規(guī)的賦值運(yùn)算外,javascript還支持需要其他的賦值運(yùn)算符,這些運(yùn)算符將賦值運(yùn)算符合其他的運(yùn)算符連接起來(lái)。提供一種更為快捷的運(yùn)算方式。例如+=運(yùn)算符執(zhí)行的是加法運(yùn)算符和賦值操作,下面的表達(dá)式:

    total += salaes_tax;
和下面的表達(dá)式等價(jià)的

total = total + salaes_tax
運(yùn)算符“+=”可以作用于數(shù)字或字符串,如果其操作是數(shù)字,它將執(zhí)行加法運(yùn)算和賦值操作;如果是字符串,他就執(zhí)行字符串的連接和賦值操作。

此類型的運(yùn)算符還包括,"-=","*=","&="等,如下表賦值運(yùn)算符

運(yùn)算符 示例 等價(jià)于
+= a+=b a=a+b
-= a-=b a=a-b
*= a*=b a=a*b
/= a/=b a=a/b
%= a%=b a=a%b
<<= a<<=b a=a<<b
>>= a>>=b a=a>>b
>>>= a>>>=b a=a>>>b
&= a&=b a=a&b
|= a|=b a=a|b
^= a^=b a=a^b
大多數(shù)情況下,表達(dá)式為

a op =b
這里的op代表一個(gè)運(yùn)算符,這個(gè)表達(dá)式等價(jià)于

a =a op b
在第一行中,表達(dá)式a計(jì)算了一次,在第二行中,表達(dá)式a計(jì)算了兩次。

只有 a包含具有副作用的表達(dá)式(比如函數(shù)調(diào)用和賦值操作)的時(shí)候,兩者才不等價(jià)。如下兩個(gè)表達(dá)式不等價(jià)

復(fù)制代碼 代碼如下:

            data[i++] *= 2;
            data[i++] = data[i++] * 2

12.表達(dá)式計(jì)算

和很多解釋性語(yǔ)言一樣,javascript同樣可以解釋運(yùn)行由javascript源代碼組成的字符串,并產(chǎn)生一個(gè)值。javascript通過(guò)全局函數(shù)eval()來(lái)完成這個(gè)工作。

eval("3+2") //=>5
動(dòng)態(tài)判斷源代碼中的字符串是一種強(qiáng)大語(yǔ)言的特性,幾乎沒(méi)有必要在實(shí)際中應(yīng)用。如果你使用了eval(),你應(yīng)該仔細(xì)考慮真的需要它。

下面降價(jià)eval()基礎(chǔ)用法,并介紹兩種嚴(yán)格使用它的方法,從代碼優(yōu)化的角度來(lái)講,這兩種方法對(duì)原有的代碼影響是最小的。

i.eval(eval()是一個(gè)函數(shù),但由于它已經(jīng)被當(dāng)做運(yùn)算符來(lái)對(duì)待了。)

eval()只有一個(gè)參數(shù),如果傳入的參數(shù)不是字符串,它直接返回這個(gè)參數(shù)。如果參數(shù)是字符串,它會(huì)把字符串當(dāng)成javascript進(jìn)行編譯(parse),如果編譯失敗則拋出一個(gè)語(yǔ)法錯(cuò)誤(SyntaxError)。如果編譯成功,則開(kāi)始執(zhí)行這段代碼,并返回字符串中最后一個(gè)表達(dá)式或語(yǔ)句的值,如果最后一個(gè)表達(dá)式?jīng)]有語(yǔ)句或者值,則最終返回undefined。如果字符串拋出一個(gè)異常,這個(gè)異常把該調(diào)用的傳給eval()

關(guān)于eveal()最重要的是,它使用了調(diào)用它的變量作用域環(huán)境,也就是說(shuō),它查找變量的值和定義新變量和函數(shù)的操作和局部的代碼作用域中的代碼一樣。如果一個(gè)函數(shù)定義了一個(gè)局部變量x,然后調(diào)用了eval("x"),它會(huì)返回局部變量的值。如果它調(diào)用eval("x=1"),它會(huì)改變局部變量的值。如果函數(shù)調(diào)用了eval("var y=3;")它聲明一個(gè)新的局部變量y。同樣的,一個(gè)函數(shù)可以通過(guò)如下代碼聲明一個(gè)局部函數(shù):

eval("function f(){return x+1;}");
如果最頂層的代碼中調(diào)用了eval()。當(dāng)然它會(huì)作用于全局變量和全局函數(shù)。

ii.全局eval()

eval()具有改變局部變量的能力,這對(duì)javascript優(yōu)化器來(lái)說(shuō),是一個(gè)很大的問(wèn)題,然而作為一種權(quán)宜之計(jì),javascript征對(duì)那行調(diào)用了eval()函數(shù)所做的優(yōu)化并不多。但當(dāng)腳本定義了一個(gè)別名,并且用令一個(gè)名稱來(lái)調(diào)用它,javascript解釋器又如何工作呢,為了javascript解釋器更加簡(jiǎn)化。ECMAScipt3標(biāo)準(zhǔn)規(guī)定了任何解釋器都不允許對(duì)eval()賦予別名。如果eval()使用別的別名來(lái)調(diào)用的話,則會(huì)拋出EvalError異常。

實(shí)際上,大多數(shù)的實(shí)現(xiàn)并不是這樣做的。當(dāng)通過(guò)別名調(diào)用時(shí),eval()會(huì)將其字符串當(dāng)成頂層的全局代碼來(lái)執(zhí)行。執(zhí)行代碼可能會(huì)定義新的全局變量和全局函數(shù)。執(zhí)行的代碼可能會(huì)定義新的全局變量和全局函數(shù),或者給全局變量賦值。但卻不能修改或修改主調(diào)函數(shù)中的局部變量,因此這不會(huì)影響到函數(shù)內(nèi)的代碼優(yōu)化。

ECMAScript5是反對(duì)使用EvalError的,并且規(guī)范了eval()的行為?!爸苯拥膃val”,當(dāng)直接使用非限定的“eval”名稱,來(lái)調(diào)用eval()函數(shù)時(shí),它總共是在它的上下文作用域內(nèi)支線。其它間接調(diào)用則使用全局函數(shù)為其上下文作用域。并且無(wú)法讀、寫、定義局部變量和函數(shù)。下面有一段代碼實(shí)例:

復(fù)制代碼 代碼如下:

var geval = eval; //使用別名調(diào)用eval將是全局eval
            var x = "global",
                y = "global"; //兩個(gè)全局變量
            function f() { //函數(shù)內(nèi)執(zhí)行的局部eval
                var x = "local" //定于局部變量
                eval("x += 'changed';"); //直接eval更改了局部變量的
                return x; //返回更改后的局部變量
            }
            function g() { //這個(gè)函數(shù)執(zhí)行了全局eval
                var y = "local" //定義了局部變量
                geval("y += 'changed';"); //間接改變了局部變量的值
                return y; //返回未更改的局部變量
            }
            console.log(f(), x); //更改了局部變量,輸出local changed global
            console.log(g(), y); //更改了全局變量,輸出local globalchanged

13.其它運(yùn)算符。

javascript支持很多其它各種各樣的運(yùn)算符。

i.條件運(yùn)算符(?:)

條件運(yùn)算符是javascript中的唯一一個(gè)三元運(yùn)算符。通常這個(gè)運(yùn)算符寫成"?:",這個(gè)運(yùn)算符擁有三哥操作數(shù),第一個(gè)操作數(shù)在"?"之前,第二個(gè)操作數(shù)在“?”和":"之間。第三個(gè)操作數(shù)早在":"之后,例如

    x > 0 ? x : -x; //求x的絕對(duì)值
條件運(yùn)算符的操作數(shù)可以是任意類型。第一個(gè)操作數(shù)當(dāng)成布爾值,如果它是真值,那么將計(jì)算第二個(gè)操作數(shù),并返回計(jì)算結(jié)果。賦值如果第一個(gè)值操作數(shù)是假值,那么將計(jì)算第三個(gè)操作數(shù)。并返回計(jì)算結(jié)果。第二個(gè)和第三個(gè)操作數(shù)總會(huì)計(jì)算其中之一。不可能兩者同時(shí)進(jìn)行。其實(shí)使用if語(yǔ)句也達(dá)到同樣的效果(5.4.1),“?:”運(yùn)算符只是提供了一種簡(jiǎn)寫形式。這里是一個(gè)"?:"的典型使用場(chǎng)景,判斷一個(gè)變量是否有定義,如果有定義則使用它,如果無(wú)定義,則使用一個(gè)默認(rèn)值。

復(fù)制代碼 代碼如下:

    grett = "hello" + (username ? username : "three");

和以下的代碼是等價(jià)的,但上面的更加簡(jiǎn)潔

復(fù)制代碼 代碼如下:

          grett = "hello";
            if (username)
                grett += username;
            else
                grett + "three"

ii.typeof()運(yùn)算符

typeof是一元運(yùn)算符,放在單個(gè)操作數(shù)前面,操作數(shù)可以是任何類型,返回值表示操作類型的一個(gè)字符串。

復(fù)制代碼 代碼如下:

            x             __ typeof x
            undefined     __ "undefined"
            null           __  "object"
            ture或false    __"boolean"
            任意數(shù)字或NaN     __ "Number"
            任意字符串                        __ "String"
            任意函數(shù)                            __ "function"
            任意內(nèi)容對(duì)象(非函數(shù))__ "object"
            任意宿主對(duì)象                    __ 由編譯器各自實(shí)現(xiàn)的字符串,但不是"undefined" "boolean" "number" "string"

typeof最常用的用法寫在表達(dá)式中們就像這樣

(typeof value == "string") ? "" + value + "":value;
typeof運(yùn)算符同樣在swith語(yǔ)句中(5.4.3)非常有用,需要注意的是,typeof運(yùn)算可以帶上園括號(hào)。這樣讓typeof看起來(lái)像一個(gè)函數(shù)名,而非關(guān)鍵字

typeof(i)

iii.delete運(yùn)算符

delete是一元操作符,它用來(lái)刪除對(duì)象的屬性或者數(shù)組的元素。就像賦值、遞增、遞減運(yùn)算符一樣。delete也是具有副作用的。它是用來(lái)做刪除操作的。不是用來(lái)返回一個(gè)值的。

復(fù)制代碼 代碼如下:

            var o = {
                x: 1,
                y: 2
            }
            delete o.x;
            "x" in o; //=>false
            var a = [1, 2, 3];
            delete a[2]; // 刪除數(shù)組中最后一個(gè)元素
            2 in a; //=> false 元素2已經(jīng)在數(shù)組中不存在了
            a.length; //=>3,注意,數(shù)組長(zhǎng)度并沒(méi)有改變,盡管上一行刪除了這個(gè)元素,但刪除操作留下了一個(gè)洞。實(shí)際上并沒(méi)有修改數(shù)組的長(zhǎng)度,因此a的長(zhǎng)度仍然為3

需要注意的是,刪除屬性或刪除數(shù)組元素不僅僅設(shè)置了一個(gè)undefined值,當(dāng)刪除一個(gè)屬性時(shí),這個(gè)屬性不復(fù)存在。讀取一個(gè)不存在的值將會(huì)返回undefined.關(guān)于delete刪除還有嚴(yán)格模式下的一些情況,需要學(xué)習(xí)的人自己試驗(yàn),這里給一些例子。

復(fù)制代碼 代碼如下:

            var o = {x: 1,y: 2};
            delete o.x; //刪除一個(gè)對(duì)象屬性,返回true
            typeof o.x; //屬性不存在,返回"undefined"
            delete o.x; //刪除不存在的屬性,返回true;
            delete o; //不能刪除通過(guò)var關(guān)鍵字聲明的變量,返回false
            delete 1; //參數(shù)不是一個(gè)左值。
            this.x = 1;// 給全局定義一個(gè)屬性,這里沒(méi)有使用var
            delete x ; //試圖刪除它,在非嚴(yán)格模式下返回true
                       //在嚴(yán)格模式下回拋出異常,這時(shí)使用"delete this.x"來(lái)代替
             x;        //運(yùn)行時(shí)出錯(cuò),沒(méi)有定義x

6章第三節(jié)還有關(guān)于delete的討論。

iii.void運(yùn)算符。

void是一元運(yùn)算符,在出現(xiàn)操作數(shù)之前,操作數(shù)可以是任何類型。這個(gè)運(yùn)算符并不是經(jīng)常使用:操作數(shù)會(huì)照常計(jì)算,但會(huì)忽略計(jì)算結(jié)果并返回undefined。由于void會(huì)忽略操作數(shù)的值,因此在操作數(shù)具有副作用時(shí)使用void來(lái)程序更有意義。

這個(gè)最常用的帶客戶端url.在url寫帶有副作用的表達(dá)式,而void則讓瀏覽器不顯示在這個(gè)表達(dá)式的運(yùn)算結(jié)果。

復(fù)制代碼 代碼如下:

    <a href="javascript:void window.open();">new</a>

iiii.逗號(hào)運(yùn)算符。(,)

逗號(hào)運(yùn)算符是二元運(yùn)算符,它的操作數(shù)可以是任意類型。它首先計(jì)算左操作數(shù),然后計(jì)算右操作數(shù)。

復(fù)制代碼 代碼如下:

    i = 0, j = 1, k = 2;

它和下面的代碼基本上等價(jià)的

i = 0; j = 1; k = 2;
總是會(huì)計(jì)算左側(cè)的表達(dá)式,但計(jì)算結(jié)果忽略掉,也就是說(shuō),只有左側(cè)表達(dá)式具有副作用,才會(huì)使用逗號(hào)運(yùn)算讓代碼變得更通暢。逗號(hào)運(yùn)算符最常用的場(chǎng)景是for循環(huán)中,這個(gè)for循環(huán)通常有多個(gè)循環(huán)變量。

復(fù)制代碼 代碼如下:

             //for循環(huán)中的第一個(gè)逗號(hào)是var語(yǔ)句的一部分
             //第二個(gè)逗號(hào)是逗號(hào)運(yùn)算符
             //它將兩個(gè)表達(dá)式(i++和j++)放在一條(for循環(huán)中)語(yǔ)句中
            for (var i = 0, j = 10; i < j; i++, j--);
            console.log(i + j);

相關(guān)文章

  • JavaScript 判斷判斷某個(gè)對(duì)象是Object還是一個(gè)Array

    JavaScript 判斷判斷某個(gè)對(duì)象是Object還是一個(gè)Array

    在開(kāi)發(fā)中,我們經(jīng)常需要判斷某個(gè)對(duì)象是否為數(shù)組類型,在Js中檢測(cè)對(duì)象類型的常見(jiàn)方法都有哪些呢?
    2010-01-01
  • 探尋Javascript執(zhí)行效率問(wèn)題

    探尋Javascript執(zhí)行效率問(wèn)題

    作為開(kāi)發(fā)人員,Web頁(yè)面加載或刷新的速度對(duì)其網(wǎng)站至關(guān)重要。開(kāi)發(fā)人員在各種瀏覽器中調(diào)試JavaScript的方法要少得多。比如,在Mozilla Firefox中,可以使用Firebug調(diào)試JavaScript,但仍然不能調(diào)整很多性能問(wèn)題,如瀏覽器呈現(xiàn)消耗時(shí)間。
    2014-11-11
  • JavaScript 中的日期和時(shí)間及表示標(biāo)準(zhǔn)介紹

    JavaScript 中的日期和時(shí)間及表示標(biāo)準(zhǔn)介紹

    本文為大家詳細(xì)介紹下時(shí)間標(biāo)準(zhǔn)指的是什么?UCT和GMT 的概念、關(guān)聯(lián)和區(qū)別?以及時(shí)間表示標(biāo)準(zhǔn)有哪些?感興趣的朋友可以參考下
    2013-08-08
  • Javascript學(xué)習(xí)筆記9 prototype封裝繼承

    Javascript學(xué)習(xí)筆記9 prototype封裝繼承

    在上文中,我利用prototype的原理做了一個(gè)封裝的New,然后我就想到,我是否可以用prototype的原理進(jìn)一步封裝面向?qū)ο蟮囊恍┗咎卣髂??比如繼承。
    2010-01-01
  • js分頁(yè)代碼分享

    js分頁(yè)代碼分享

    這篇文章主要介紹了js分頁(yè)代碼示例,很簡(jiǎn)單的代碼,需要的朋友可以參考下
    2014-04-04
  • 詳解JavaScript中g(shù)etFullYear()方法的使用

    詳解JavaScript中g(shù)etFullYear()方法的使用

    這篇文章主要介紹了詳解JavaScript中g(shù)etFullYear()方法的使用,是JS入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-06-06
  • javaScript知識(shí)點(diǎn)總結(jié)(必看篇)

    javaScript知識(shí)點(diǎn)總結(jié)(必看篇)

    下面小編就為大家?guī)?lái)一篇javaScript知識(shí)點(diǎn)總結(jié)(必看篇)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享 給大家,也給的大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-06-06
  • 徹底搞懂?javascript的Promise

    徹底搞懂?javascript的Promise

    這篇文章主要為大家詳細(xì)介紹了javascript的Promise,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • JS之if語(yǔ)句對(duì)接事件動(dòng)作邏輯(詳解)

    JS之if語(yǔ)句對(duì)接事件動(dòng)作邏輯(詳解)

    下面小編就為大家?guī)?lái)一篇JS之if語(yǔ)句對(duì)接事件動(dòng)作邏輯(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • 簡(jiǎn)介JavaScript中substring()方法的使用

    簡(jiǎn)介JavaScript中substring()方法的使用

    這篇文章主要介紹了簡(jiǎn)介JavaScript中substring()方法的使用,是JS入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-06-06

最新評(píng)論