謂操作符,就是用來操作數(shù)據(jù)值的符號,在JavaScript中包括算術(shù)操作符、位操作符、關(guān)系操作符和相等操作符。這些操作符可以操作所有類型的數(shù)據(jù),比如字符串、數(shù)字、布爾值,甚至對象。
所謂一元操作符就是只能對一個數(shù)據(jù)值進行操作,比如(遞增、遞減)操作符。
遞增、遞減操作符是直接借鑒C語言的,它分前置型和后置型。前置就是操作符在要操作的變量之前,后置在變量之后。
如下示例:
// 前置型
let age = 20;
++age; // 遞增
console.log(age); // 結(jié)果輸出21
--age;//遞減
console.log(age); // 結(jié)果輸出20
如上面例子,age通過++操作符遞增變成21,又通過--操作符遞減變成20;上面的操作等同下面的操作:
// 后置型
let age = 20;
age = age + 1; // 加1
age = age -1; // 減1
同理使用后置操作符會得到上面同樣的結(jié)果,但是前置和后置有區(qū)別。前置操作符在語句被求值以前改變,后置是在語句被求值后改變。通過下面的例子看下其區(qū)別:
// 前置
let age = 20;
let anotherAge = --age + 5;
alert(age); // 輸出19
alert(anotherAge); // 輸出24
由于前置操作符的優(yōu)先級和執(zhí)行語句相等,因此會從左到右依次求值。上面的--age 會先進行遞減操作,再繼續(xù)后面的 + 5 運算,所以結(jié)果是24。
// 后置時
let age = 20;
let anotherAge = age-- + 5;
alert(age); // 輸出19
alert(anotherAge); // 輸出25
但是后置的最終結(jié)果卻是25,因為age-- 使用了遞減前的值繼續(xù)和后面進行+5運算。
如果使用一個加號或減號時,加號代表正值、減號代表負值。
操作多個數(shù)據(jù)值,比如加減乘除等:
let a = 1,b=2;
let c = a + b; // 加
let d = c - a; // 減
let e = d * b; // 乘
let f = e/d; // 除
注意加減乘除主要用來操作數(shù)字類型的數(shù)據(jù),如果操作數(shù)不是數(shù)字類型,會先進性強制轉(zhuǎn)換再進行計算,這樣結(jié)果會不確定。
位操作符,是指按內(nèi)存中的表示的數(shù)值位來操作數(shù)值,通俗講就是用來操作二進制的數(shù)據(jù)。二進制數(shù)據(jù)都是由0、1組成的,在JavaScript中所有數(shù)值都是64位的格式存儲,但位操作符不直接在64位的值上進行計算,會先轉(zhuǎn)化成32位后再運算。位操作符有以下幾種:
按位非(NOT)
按位非操作符是(~)符號,就是將二進制中每位數(shù)值進行反碼操作。其規(guī)則如下:
操作符 | 數(shù)值 | 結(jié)果 |
~ | 1 | 0 |
~ | 0 | 1 |
如下示例:
let a = 25;
let b = ~a;
alert(b); // 輸出-26
按位與(AND)
使用(&)符號表示,它有2個操作數(shù),當2個數(shù)對應的位都是1時返回1,任何一位是0則返回0。如下規(guī)則:
數(shù)值1 | 操作符 | 數(shù)值2 | 結(jié)果 |
1 | & | 1 | 1 |
1 | & | 0 | 0 |
0 | & | 1 | 0 |
0 | & | 0 | 0 |
示例:
let a = 25 & 3;
alert(a); // 輸出結(jié)果是1
按位或(OR)
用(|)符號表示,同樣也是2個操作數(shù)。其規(guī)則是只要有一位是1其結(jié)果就是1,負則結(jié)果是0;
數(shù)值1 | 操作符 | 數(shù)值2 | 結(jié)果 |
1 | | | 1 | 1 |
1 | | | 0 | 1 |
0 | | | 1 | 1 |
0 | | | 0 | 0 |
示例:
let a = 25 | 3;
alert(a); // 輸出結(jié)果是27
按位異或(XOR)
由(^)符號表示,也是操作2個操作數(shù),其當2個操作數(shù)的位值相同時返回0,負則返回1。
數(shù)值1 | 操作符 | 數(shù)值2 | 結(jié)果 |
1 | ^ | 1 | 0 |
1 | ^ | 0 | 1 |
0 | ^ | 1 | 1 |
0 | ^ | 0 | 0 |
示例:
let a = 25 ^ 3;
alert(a); // 輸出結(jié)果是26
左移
使用(<<)兩個小于號表示,這個操作符會將數(shù)值每一位向左移動指定位數(shù)。如下示例:
let a = 2; // 二進制 10
let b = b << 5; // 二進制的 1000000,十進制64
上面,將二進制10向左移動5位,注意左移會多出5個空位,用0來填充,這樣就會得到一個完整的32位二進制數(shù)據(jù)。
注意,左移不會影響符號位(二進制位中第一位表示數(shù)的正負),如-2 向左移5位結(jié)果是-64。
有符號的右移
使用(>>)兩個大于號表示,會將每位向右移動指定位數(shù),但保留符號位(即正負號標記)。如下示例:
let a = 64; // 二進制 1000000
let b = b >> 5; // 二進制的 10,十進制的2
在移位過程,原數(shù)中也會出現(xiàn)空位,只不過這次空位出現(xiàn)在原數(shù)值左側(cè)、符號位右側(cè)。空位使用符號位值填充。
有符號的整數(shù),指32位中前31位表示整數(shù)的值,第32位表示數(shù)值的符號,0正數(shù),1負數(shù)。這個表示符號的位就是符號位。
無符號的右移
使用(>>>)三個大于號表示,這個操作會將所有32位都向右移動。對于正數(shù)其結(jié)果和有符號的右移一樣,如下示例:
let a = 64; // 二進制 1000000
let b = b >>> 5; // 二進制的 10,十進制的2
但是負數(shù)就不一樣了,無符號的右移是以0來填充空位,不像有符號右移使用符號位填充。所以其結(jié)果相差很大,如下示例:
let a = -64; // 二進制 1111 1111 1111 1111 1111 1111 1100 0000
let b = b >>> 5; // 二進制 0000 0111 1111 1111 1111 1111 1111 1110 ,十進制的134217726
在任何編程語言中,布爾操作符都是非常重要的,它是用來判斷邏輯的關(guān)鍵,布爾操作符一共有三種:非(NOT)、與(AND)、或(OR)。
邏輯非
使用(!)感嘆號表示邏輯非,其規(guī)則就是:
操作符 | 邏輯值 | 結(jié)果 |
! | true | false |
! | false | true |
邏輯與
使用(&&)表示,操作兩個數(shù),如下示例:
let a = ture && false;
其規(guī)則如下:
邏輯值1 | 操作符 | 邏輯值2 | 結(jié)果 |
ture | && | ture | ture |
ture | && | false | false |
false | && | ture | false |
false | && | false | false |
也就是只有當2個數(shù)值都是true時其結(jié)果才是true。
邏輯或
使用(||)符號表示,也是有兩個操作數(shù),其示例:
let a = true || false;
規(guī)則如下:
邏輯值1 | 操作符 | 邏輯值2 | 結(jié)果 |
ture | || | ture | ture |
ture | || | false | ture |
false | || | ture | ture |
false | || | false | false |
也就是2個操作數(shù)中有一個true,結(jié)果就是true,負則是false。
注意布爾操作符,不僅僅可以操作布爾類型值,對于其它數(shù)據(jù)類型同樣適用,只不過會先將其它數(shù)據(jù)類型轉(zhuǎn)換成布爾值,再進行布爾運算。如下示例:
let a = !1; // 輸出false
let b = !'string'; // 輸出false
let c = 1 || 0; // 輸出true
let e = 1 && 0;// 輸出false
let d = ''&& 2; // 輸出true
關(guān)系操作符用來比較2個操作數(shù),有小于(<)、大于(>)、小于等于(<=)和大于等于(>=)。其比較的結(jié)果返回一個布爾值,true或false。
如下示例:
let a = 5 > 3; // true
let b = 5 < 3; // false
同樣,關(guān)系操作符也可以適用其它類型的數(shù)據(jù),比如字符串比較大小時,會按照字符的編碼大小比較。如下示例:
let a = "Brick" < "alphabet"; // true,
上面中因為B字符編碼是66,a的編碼是97,所以返回true。
在編程中,確定2個值是否相等是一個非常重要的操作。在JavaScript中分相等(==)和全等(===)、不等(!=)和不全等(!==)四種。
相等(==)和不相等(!=)
如下示例:
let a = 1 == 1; // true
let b = 1==0;// false
let c = 1!=1; // false
let d = 1!=0; //true
注意相等和不相等的操作前會先對操作性進行強制轉(zhuǎn)換,如下示例:
let a = true == 1; // 先將true轉(zhuǎn)換成1再比較,結(jié)果是true
let b = false == 1; // 先將false轉(zhuǎn)換成0再比較,結(jié)果是false
全相等(===)和不全相等(!==)
全等和不全等不同之處是,它在比較數(shù)據(jù)前,不進行數(shù)據(jù)類型轉(zhuǎn)換,是對原始數(shù)值比較,所以它的結(jié)果更加嚴格準確,如下示例:
let a = 1 === 1; // true
let b = 1=== '1';// false
let c = 1!==1; // false
let d = 1!=='1'; //true
注意和之前相等和不相等的例子比較,其結(jié)果非常不一樣。
使用(=)表示賦值操作,其作用就是把等號右側(cè)的值賦值給左邊的變量或?qū)傩裕缦率纠?/p>
let a = 10; // 給a變量賦值10
如果在等號前面加上其它操作符,就組成了復合型賦值操作,如下示例:
let a = 10;
a += 5; // 結(jié)果是 15
上面的等同于下面:
let a = 10;
a = a + 5; // 結(jié)果是 15
當然也可以使用其它操作符,如(*=)、(/=)、(%=)、(-=)、(<<=)等等。
也稱三目運算符,它是一種簡便的條件運算,可以把它看成是if else的簡化,其語法如下:
變量 = 布爾表達式 ? true_value : false_value
先求出問號前面的布爾表示結(jié)果,如果是true,變量使用冒號前面的值,負則使用冒號后面的值。如下示例:
let a = 5 > 3 ? '好' : '不好'; // 結(jié)果是 '好'
使用(,)符號,表示可以執(zhí)行多個操作,常用于變量定義或函數(shù)參數(shù),如下示例:
var a = 0,b=1,c=2; // a、b、c使用逗號隔開
let a,b,c;
// 函數(shù)中的參數(shù)a、b、c使用逗號隔開
function test(a,b,c){
// 函數(shù)主體
}
// 調(diào)用函數(shù)
test(1,2,3)
本節(jié)主要講述了JavaScript中所有的操作符概念,這些都是最基本的知識,需要完全掌握。在平常工作中其中除了位操作符不常用外,其它操作符使用頻率很高,尤其是布爾操作符,算術(shù)操作符,比較操作符等。
本篇只是大概講述了操作符的概念和使用方法,還有一些細節(jié)沒有講到,作為入門課程已經(jīng)足夠了,你可以自己搜索每個知識點詳細內(nèi)容,比如關(guān)于二進制數(shù)據(jù)、位操作、數(shù)據(jù)類型強制轉(zhuǎn)換等,這里不再詳細介紹。
《JavaScript 高級程序設(shè)計》
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
https://www.w3cschool.cn/javascript/js-operators.html
SS Padding(填充)屬性定義元素邊框與元素內(nèi)容之間的空間。
Padding(填充)
當元素的 Padding(填充)(內(nèi)邊距)被清除時,所"釋放"的區(qū)域?qū)艿皆乇尘邦伾奶畛洹?/p>
單獨使用填充屬性可以改變上下左右的填充。縮寫填充屬性也可以使用,一旦改變一切都改變。
可能的值
值 | 說明 |
---|---|
length | 定義一個固定的填充(像素, pt, em,等) |
% | 使用百分比值定義一個填充 |
填充- 單邊內(nèi)邊距屬性
在CSS中,它可以指定不同的側(cè)面不同的填充:
實例
padding-top:25px;
padding-bottom:25px;
padding-right:50px;
padding-left:50px;
填充 - 簡寫屬性
為了縮短代碼,它可以在一個屬性中指定的所有填充屬性。
這就是所謂的縮寫屬性。所有的填充屬性的縮寫屬性是"padding":
實例
padding:25px 50px;
嘗試一下 ?
Padding屬性,可以有一到四個值。
padding:25px 50px 75px 100px;
上填充為25px
右填充為50px
下填充為75px
左填充為100px
padding:25px 50px 75px;
上填充為25px
左右填充為50px
下填充為75px
padding:25px 50px;
上下填充為25px
左右填充為50px
padding:25px;
所有的填充都是25px
更多實例
在一個聲明中的所有填充屬性
這個例子演示了使用縮寫屬性設(shè)置在一個聲明中的所有填充屬性,可以有一到四個值。
設(shè)置左部填充
這個例子演示了如何設(shè)置元素左填充。
設(shè)置右部填充
這個例子演示了如何設(shè)置元素右填充。.
設(shè)置上部填充
這個例子演示了如何設(shè)置元素上填充。
設(shè)置下部填充
這個例子演示了如何設(shè)置元素下填充。
所有的CSS填充屬性
屬性 | 說明 |
---|---|
padding | 使用縮寫屬性設(shè)置在一個聲明中的所有填充屬性 |
padding-bottom | 設(shè)置元素的底部填充 |
padding-left | 設(shè)置元素的左部填充 |
padding-right | 設(shè)置元素的右部填充 |
padding-top | 設(shè)置元素的頂部填充 |
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
天扣丁小編給大家總結(jié)一下關(guān)于經(jīng)常在a標簽中看到href="javascript:void(0),但是并沒有認真的研究過,正好看到了這篇文章,漲漲姿勢。
請輸入圖片描述
由于JS表達式偏啰嗦,于是最近便開始采用Coffeescript來減輕負擔。舉個栗子,當我想取屋子里的第一條dog時,首先要判斷house對象是否存在,然后再判斷house.dogs是否存在,最后取house.dogs[0]。在JS需要這么寫
vardog=(typeofhouse!=='undefined&&house!==null)&&house.dogs&&house.dogs[0]
在Coffee中,我只需要這么寫:
dog=house?.dogs?[0];
寫到這里,讀者會問,這跟標題《Javascript中的void》有一毛錢關(guān)系?Coffee的本質(zhì)就是JS,之所以Coffee能工作的很好,是因為它生成出了高效而且健壯的JS代碼,我們可以看看它的生成結(jié)果。
vardog,_ref;
dog=typeofhouse!=="undefined"&&house!==null?(_ref=house.dogs)!=null?_ref[0]:void0:void0;
短短一行Coffee代碼生成出了如此長的JS代碼,看上去似乎比我最前面自己用JS寫的更靠譜更安全,末尾還出來了兩個void0,這究竟是何方神圣?
結(jié)構(gòu)化一下上面的例子:
dog=(typeofhouse!=="undefined"&&house!==null)?
((_ref=house.dogs)!=null?_ref[0]:void0)
:void0;
如果house未定義或house為null時,返回void0
如果house.dogs為null時,返回void0
可void0究竟是什么值,這個倒很容易測試:
typeofvoid0//得到"undefined"
console.log(void0)//輸出undefined
似乎void0就是undefined了,但這樣子路數(shù)太野,也不夠嚴謹,即無法回答:void100,voidhello(),voidi++這無數(shù)可能組合的值是什么?
我們來瞅瞅規(guī)范是怎么說的吧。
規(guī)范是這么說的
在ECMAScript262規(guī)范,有如下描述:
ThevoidOperator
TheproductionUnaryExpression:voidUnaryExpressionisevaluatedasfollows:
LetexprbetheresultofevaluatingUnaryExpression.
CallGetValue(expr).
Returnundefined.
NOTE:GetValuemustbecalledeventhoughitsvalueisnotusedbecauseitmayhaveobservableside-effects.
搬譯一下:
void操作符
產(chǎn)生式UnaryExpression:voidUnaryExpression按如下流程解釋:
令expr為解釋執(zhí)行UnaryExpression的結(jié)果。
調(diào)用GetValue(expr).
返回undefined.
注意:GetValue一定要調(diào)用,即使它的值不會被用到,但是這個表達式可能會有副作用(side-effects)。
重點在于:無論void后的表達式是什么,void操作符都會返回undefined.因此上面由Coffee編譯出來的代碼我們可以認為是這樣的:
dog=(typeofhouse!=="undefined"&&house!==null)?
((_ref=house.dogs)!=null?_ref[0]:undefined)
:undefined;
問題來了,既然(void0)===undefined,那直接寫undefined不就行了么?
為什么要用void?
因為undefined在javascript中不是保留字。換言之,你可以寫出:
functionjoke(){
varundefined="helloworld";
console.log(undefined);//會輸出"helloworld"
}
console.log(undefined);//輸出undefined
對的,你可以在一個函數(shù)上下文內(nèi)以undefined做為變量名,于是在這個上下文寫的代碼便只能通過從全局作用域來取到undefined,如:
window.undefined//瀏覽器環(huán)境
GLOBAL.undefined//Node環(huán)境
但要注意的是,即便window,GLOBAL仍然可以在函數(shù)上下文被定義,故從window/GLOBAL上取undefined并不是100%可靠的做法。如:
functionx(){
varundefined='helloworld',
f={},
window={
'undefined':'joke'
};
console.log(undefined);//helloworld
console.log(window.undefined);//joke
console.log(f.a===undefined);//false
console.log(f.a===void0);//true
}
于是,采用void方式獲取undefined便成了通用準則。如underscore.js里的isUndefined便是這么寫的:
_.isUndefined=function(obj){
returnobj===void0;
}
除了采用void能保證取到undefined值以外,還有其它方法嗎?有的,還有一種方式是通過函數(shù)調(diào)用。如AngularJS的源碼里就用這樣的方式:
(function(window,document,undefined){
//.....
})(window,document);
通過不傳參數(shù),確保了undefined參數(shù)的值是一個undefined。
其它作用
除了取undefined外,void還有什么其它用處嗎?
還有一個常見的功能,填充href。下面是一個微博截圖,它的轉(zhuǎn)發(fā),收藏,討論都是超鏈接,但是用戶并不希望點擊它們會跳轉(zhuǎn)到另一個頁面,而是引發(fā)出一些交互操作。
理論上而言,這三個超鏈接都是沒有URL的,但如果不寫的話,呵呵,點擊它會刷新整個頁面。于是便用上了href="javascript:void(0)的方式,確保點擊它會執(zhí)行一個純粹無聊的void(0)。
另一種情況是,如果我們要生成一個空的src的image,最好的方式似乎也是src='javascript:void(0)',參見StackOverflow上的這個問題:What’sthevalidwaytoincludeanimagewithnosrc?
寫在最后
回到void的定義,有一句話特別讓人迷惑:
注意:GetValue一定要調(diào)用,即使它的值不會被用到,但是這個表達式可能會有副作用(side-effects)。
這是什么意思?這表示無論void右邊的表達式是什么,都要對其求值。這么說可能不太明白,在知乎上有過闡述關(guān)于js中void,既然返回永遠是undefined,那么GetValue有啥用?,我且拾人牙慧,代入一個場景,看代碼:
varhappiness=10;
vargirl={
getwhenMarry(){
happiness--;
return1/0;//Infinity
},
gethappiness(){
returnhappiness;
}
};
console.log(girl.whenMarry);//調(diào)用了whenMarry的get方法
console.log(girl.happiness);//9
voidgirl.whenMarry;//調(diào)用了whenMarry的get方法
console.log(girl.happiness);//8
deletegirl.whenMarry;//沒有調(diào)用whenMarry的get方法
console.log(girl.happiness);//還是8
上述代碼定義了一個大齡文藝女青年,每被問到什么時候結(jié)婚呀(whenMarry),happiness都會減1。從執(zhí)行情況可以看出,無論是普通訪問girl.whenMarry,還是voidgirl.whenMarry都會使她的happiness--。而如果把void換成delete操作符寫成deletegirl.whenMarry,她的happiness就不會減了,因為delete操作符不會對girl.whenMarry求值。
總結(jié)
void有如下作用:
通過采用void0取undefined比采用字面上的undefined更靠譜更安全,應該優(yōu)先采用void0這種方式。
填充
(href和src中采用javascript:偽協(xié)議,導致瀏覽器會執(zhí)行后面的代碼,根據(jù)返回值來決定下一步操作,當返回值是undefined時瀏覽器不會把返回值替換頁面里的內(nèi)容,也就不會導致href和src的值發(fā)生改變)
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。