RYF javascript筆記1

標(biāo)簽: 我的筆記

---學(xué)習(xí)資料:http://javascript.ruanyifeng.com/

1. 導(dǎo)論

  • JavaScript的發(fā)明目的,就是作為瀏覽器的內(nèi)置腳本語(yǔ)言矫膨,為網(wǎng)頁(yè)開(kāi)發(fā)者提供操控瀏覽器的能力届搁。

  • 近年來(lái)脑又,JavaScript的使用范圍贝淤,慢慢超越了瀏覽器眉睹,正在向通用的系統(tǒng)語(yǔ)言發(fā)展。

  • “任何能夠用JavaScript實(shí)現(xiàn)的應(yīng)用霞揉,最終都必將用JavaScript實(shí)現(xiàn)∥铮”

2. 基本語(yǔ)法

2.1 基本句法和變量

2.1.1 語(yǔ)句

  • JavaScript程序的執(zhí)行單位為行(line)适秩,一般一行就是一個(gè)語(yǔ)句。

    var a = 1 + 3 ;

這是一條語(yǔ)句,其中“1+3”叫做表達(dá)式秽荞。

  • 語(yǔ)句和表達(dá)式的區(qū)別在于:前者主要為了進(jìn)行某種操作骤公,后者則是為了得到返回值

  • 語(yǔ)句以分號(hào)結(jié)尾表達(dá)式不需要分號(hào)結(jié)尾扬跋,否則會(huì)變成無(wú)任何意義的語(yǔ)句)阶捆,一個(gè)分號(hào)就表示一個(gè)語(yǔ)句結(jié)束。多個(gè)語(yǔ)句可以寫在一行內(nèi)钦听。

  • 分號(hào)前面可以沒(méi)有任何內(nèi)容;洒试,這叫做空語(yǔ)句。

2.1.2 變量

  • 變量是對(duì)“值”的引用朴上,變量有聲明和賦值兩個(gè)步驟垒棋。

    var a = 1;

相當(dāng)于:

var a;
a = 1;
  • 只聲明變量而不賦值,則該變量的值為undefined痪宰。

    var a;
    a //undefined

  • 不聲明而直接使用會(huì)報(bào)錯(cuò):

    x //ReferenceError: x is not defined

  • JavaScript允許省略var捕犬,這樣創(chuàng)建的是全局變量,建議總是使用var酵镜。

2.1.3 變量提升

  • JavaScript引擎的工作方式:先解析代碼碉碉,將所有的變量聲明提升(hoisting)到代碼的頭部,再一行一行地運(yùn)行淮韭。

比如:

console.log(a); //undefined
var a = 1; //var a垢粮;被提升

上面代碼不會(huì)打印出1,但不會(huì)報(bào)錯(cuò)靠粪。因?yàn)榇嬖谧兞刻嵘桑哉嬲\(yùn)行的是:

var a;
console.log(a);
a = 1;
  • 請(qǐng)注意,變量提升只對(duì)var命令聲明的變量有效占键,如果變量不是用var命令聲明的就不會(huì)發(fā)生變量提升昔善。因?yàn)镴avaScript引擎將其視為對(duì)頂層對(duì)象的b屬性進(jìn)行賦值。

比如:

console.log(b); //ReferenceError: b is not defined
b = 1; //沒(méi)有變量聲明被提升

2.1.4 標(biāo)識(shí)符

  • 標(biāo)識(shí)符用來(lái)識(shí)別具體對(duì)象畔乙。最常見(jiàn)的標(biāo)識(shí)符就是變量名和函數(shù)名君仆。
  • JavaScript語(yǔ)言的標(biāo)識(shí)符對(duì)大小寫敏感。
  • 標(biāo)識(shí)符的命名規(guī)則:
  • 第1個(gè)字符可以是任意Unicode字母牲距,以及美元符號(hào)($)和下劃線(_)返咱。
  • 其它字符,還可以用數(shù)字牍鞠。
  • JavaScript的保留字不能用作標(biāo)識(shí)符咖摹。
  • 保留字有:var、void难述、class萤晴、if吐句、for、new店读、null蕴侧、true、return 等两入。
  • 還有特別含義的標(biāo)識(shí)符:Infinity净宵、NaN、undefined裹纳。

2.1.5 注釋

  • 單行注釋择葡,用//起頭
  • 多行注釋,放在/* 和 */之間

比如:

// 單行注釋
/*
 多行
 注釋
*/

2.1.6 區(qū)塊

  • 一組大括號(hào)包起來(lái)的多條語(yǔ)句剃氧,稱為“區(qū)塊”(block)敏储。

  • 與大多數(shù)編程語(yǔ)言不一樣,JavaScript的區(qū)塊不構(gòu)成單獨(dú)的作用域(scope)朋鞍。

比如:

{
    var a = 1;
}
a // 1

類似的C#代碼則會(huì)報(bào)錯(cuò):

{
    var a = 1;
}
Console.WriteLine(a); //當(dāng)前上下文中不存在名稱“a”

2.1.7 條件語(yǔ)句

a. if

if (m === 3) 
  m += 1;

if (m === 0) {
    // ...
} else if (m === 1) {
   // ...
} else {
   // ...
}

else代碼塊總是跟隨離自己最近的那個(gè)if語(yǔ)句已添。

b. switch

  • 建議case內(nèi)部必須有break
    因?yàn)閏ase內(nèi)部如果沒(méi)有break就會(huì)接著執(zhí)行下一個(gè)case部分(而且不判斷case條件)。

  • switch語(yǔ)句部分和case語(yǔ)句部分滥酥,都可以使用表達(dá)式更舞。

  • switch后面的表達(dá)式與case后面的表示式比較時(shí),采用的是嚴(yán)格相等運(yùn)算符(===)坎吻,而不是相等運(yùn)算符(==)缆蝉。

這意味著比較時(shí)不會(huì)發(fā)生類型轉(zhuǎn)換:

console.log(4=="4");
console.log(4==="4");
switch(1 + 3) {
    case "4":
        console.log("string 4");
        break;
    case 2 + 2:
        console.log("number 4");
    case 2 + 3:
        console.log("number 5");
        break;
    default:
        console.log("default");
}

上面代碼會(huì)輸出:
true
false
number 4 //因?yàn)?==="4"是false,而4===4是true
number 5 //因?yàn)閏ase 2 + 2 語(yǔ)句內(nèi)部沒(méi)有使用break

  • switch結(jié)構(gòu)不利于代碼重用瘦真,往往可以用對(duì)象形式重寫刊头。

比如:

var o = {
    banana: function (){ console.log("banana"); },
    apple: function (){ console.log("apple"); },
    default: function (){ console.log("default"); }
};
var fruit="apple";
if (o[fruit]){
    o[fruit]();
} else {
    o['default']();
}

輸出apple

2.1.8 循環(huán)語(yǔ)句

a. while循環(huán)

如果條件為真,就不斷循環(huán)诸尽。

var i = 0;
while (i<100){
    console.log('i當(dāng)前為:' + i);
    i++;
}

b. for循環(huán)

for語(yǔ)句分成三步:

  • 初始化(initialize):確定循環(huán)的初始值原杂,只執(zhí)行一次;

  • 檢測(cè)(test):檢測(cè)循環(huán)條件,只要為真就進(jìn)行后續(xù)操作;

  • 遞增(increment):當(dāng)循環(huán)體執(zhí)行完畢后您机,執(zhí)行遞增操作穿肄,然后重新檢測(cè)。

    for (var i=0; i < arr.length; i++) {
    console.log(arr[i]);
    }

for語(yǔ)句表達(dá)式的三個(gè)部分可以省略任何一個(gè)或全部省略往产。

var i=0;
for (; i < 10; ) {
    console.log(i++);
}

所有for循環(huán)被碗,都可以改寫成while循環(huán)某宪。

c. do...while循環(huán)

  • do...while循環(huán)與while循環(huán)類似仿村,唯一的區(qū)別就是先運(yùn)行一次循環(huán)體,然后判斷循環(huán)條件兴喂。
  • 另外蔼囊,while語(yǔ)句后面的分號(hào)不能省略:

至少運(yùn)行一次焚志,這是這種結(jié)構(gòu)最大的特點(diǎn)。

do { 
    statement
} while(expression);

d. break語(yǔ)句和continue語(yǔ)句

  • break語(yǔ)句用于跳出代碼塊或循環(huán)畏鼓。
  • continue語(yǔ)句用于立即終止本次循環(huán)酱酬,開(kāi)始下一次循環(huán)。

e. 標(biāo)簽(label)

不建議使用云矫。

2.1.9 結(jié)尾的分號(hào)

a. 不使用分號(hào)結(jié)尾的語(yǔ)句

}結(jié)尾的語(yǔ)句不需要分號(hào)結(jié)束膳沽,如:for、while让禀、if挑社, switch, try巡揍、函數(shù)
因此痛阻,do...while需要分號(hào)結(jié)束

b. 分號(hào)的自動(dòng)添加

JavaScript引擎在應(yīng)該寫卻沒(méi)寫的情況下,會(huì)自動(dòng)添加分號(hào)腮敌。
但這難以預(yù)測(cè)阱当,因此不應(yīng)省略該有的分號(hào)。

2.2 數(shù)據(jù)類型

2.2.1 概述

六個(gè)類別和兩個(gè)特殊值糜工。

原始類型:

數(shù)值(number)    //整數(shù)和小數(shù)
字符串(string)
布爾值(boolean)

合成類型:

對(duì)象(object)
數(shù)組(array)
函數(shù)(function)

兩個(gè)特殊值nullundefined

2.2.2 typeof運(yùn)算符

JavaScript有三種方法弊添,可以確定一個(gè)值到底是什么類型。

typeof運(yùn)算符
instanceof運(yùn)算符
Object.prototype.toString方法
  1. 原始類型分別返回number捌木、string表箭、boolean
  2. 函數(shù)返回function
  3. undefined返回undefined

利用這一點(diǎn)來(lái)檢查一個(gè)沒(méi)有聲明的變量,而不報(bào)錯(cuò)钮莲。

if (typeof v === "undefined"){
    // ...
}
  1. 除此以外免钻,都返回object。

對(duì)象崔拥、數(shù)組极舔、null

typeof window // "object"
typeof {} // "object"
typeof [] // "object"
typeof null // "object"

說(shuō)明數(shù)組本質(zhì)上只是一種特殊的對(duì)象。
null的類型也是object链瓦,這是歷史原因造成的拆魏,它是一個(gè)類似于undefined的特殊值。

區(qū)分?jǐn)?shù)組和對(duì)象

console.log(({}) instanceof Array); // false
console.log([] instanceof Array); // true
console.log(({}) instanceof Object); // true
console.log([] instanceof Object); // true

2.2.3 null和undefined

  • 幾乎等價(jià)慈俯。

如:

console.log(undefined == null); // true
console.log(undefined === null); // false
  • 大致可以區(qū)分:
    null表示"沒(méi)有對(duì)象"渤刃,即該處不應(yīng)該有值。
    undefined表示"缺少值"贴膘,即此處應(yīng)該有值卖子,但是還未定義。

  • null的特殊之處在于:typeof null 結(jié)果為Object

2.2.4 布爾值

如果JavaScript預(yù)期某個(gè)位置應(yīng)該是布爾值刑峡,會(huì)將該位置上現(xiàn)有的值自動(dòng)轉(zhuǎn)為布爾值洋闽。

轉(zhuǎn)換規(guī)則是除了下面6個(gè)值被轉(zhuǎn)為false玄柠,其他值都視為true。

  • undefined
  • null
  • false
  • 0
  • NaN
  • ""(空字符串)

2.2.5 類型轉(zhuǎn)換

JavaScript是一種動(dòng)態(tài)類型語(yǔ)言诫舅,變量是沒(méi)有類型的羽利,可以隨時(shí)賦予任意值。但是刊懈,數(shù)據(jù)本身和各種運(yùn)算是有類型的这弧,因此運(yùn)算時(shí)變量需要轉(zhuǎn)換類型。

a. 強(qiáng)制轉(zhuǎn)換

強(qiáng)制轉(zhuǎn)換主要指使用Number虚汛、String和Boolean三個(gè)構(gòu)造函數(shù)当宴,手動(dòng)將各種類型的值,轉(zhuǎn)換成數(shù)字泽疆、字符串或者布爾值户矢。

Number函數(shù)

1、原始類型:

  • 數(shù)值:轉(zhuǎn)換后還是原來(lái)的值殉疼。
  • 字符串:如果可以被解析為數(shù)值梯浪,則轉(zhuǎn)換為相應(yīng)的數(shù)值,否則得到NaN瓢娜」衣澹空字符串轉(zhuǎn)為0。
  • 布爾值:true轉(zhuǎn)成1眠砾,false轉(zhuǎn)成0虏劲。
  • undefined:轉(zhuǎn)成NaN。 null:轉(zhuǎn)成0褒颈。

Number函數(shù)和parseInt函數(shù)的區(qū)別:

  • parseInt逐個(gè)解析字符柒巫,而Number函數(shù)整體轉(zhuǎn)換字符串的類型。
  • Number會(huì)忽略八進(jìn)制的前導(dǎo)0谷丸,而parseInt不會(huì)堡掏。
  • Number函數(shù)會(huì)自動(dòng)過(guò)濾一個(gè)字符串前導(dǎo)和后綴的空格。

示例:

parseInt('011') // 9
parseInt('42 cats') // 42
parseInt('0xcafebabe') // 3405691582

Number('011') // 11
Number('42 cats') // NaN
Number('0xcafebabe') // 3405691582

2刨疼、對(duì)象

  • 1.先調(diào)用對(duì)象自身的valueOf方法泉唁,如果該方法返回原始類型的值(數(shù)值、字符串和布爾值)揩慕,則直接對(duì)該值使用Number方法亭畜,不再進(jìn)行后續(xù)步驟。
  • 2.如果valueOf方法返回復(fù)合類型的值迎卤,再調(diào)用對(duì)象自身的toString方法拴鸵,如果toString方法返回原始類型的值,則對(duì)該值使用Number方法,不再進(jìn)行后續(xù)步驟宝踪。
  • 3.如果toString方法返回的是復(fù)合類型的值侨糟,則報(bào)錯(cuò)碍扔。
String函數(shù)

1瘩燥、原始類型:

  • 數(shù)值:轉(zhuǎn)為相應(yīng)的字符串。
  • 字符串:轉(zhuǎn)換后還是原來(lái)的值不同。
  • 布爾值:true轉(zhuǎn)為“true”厉膀,false轉(zhuǎn)為“false”。
  • undefined:轉(zhuǎn)為“undefined”二拐。 null:轉(zhuǎn)為“null”服鹅。

2、對(duì)象:

  • 先調(diào)用toString方法百新,如果toString方法返回的是原始類型的值企软,則對(duì)該值使用String方法,不再進(jìn)行以下步驟饭望。
  • 如果toString方法返回的是復(fù)合類型的值仗哨,再調(diào)用valueOf方法,如果valueOf方法返回的是原始類型的值铅辞,則對(duì)該值使用String方法厌漂,不再進(jìn)行以下步驟。
  • 如果valueOf方法返回的是復(fù)合類型的值斟珊,則報(bào)錯(cuò)苇倡。

String方法的這種過(guò)程正好與Number方法相反。

Boolean函數(shù)

1囤踩、原始類型:

以下六個(gè)值的轉(zhuǎn)化結(jié)果為false旨椒,其他的值全部為true。

  • undefined
  • null
  • -0
  • +0
  • NaN
  • ''(空字符串)

2堵漱、對(duì)象:

所有對(duì)象的布爾值都是true钩乍,甚至連false對(duì)應(yīng)的布爾對(duì)象也是true。
空對(duì)象{}和空數(shù)組[]也會(huì)被轉(zhuǎn)成true怔锌。

Boolean(new Boolean(false)) // true
Boolean([]) // true
Boolean({}) // true

b. 自動(dòng)轉(zhuǎn)換

有時(shí)JavaScript會(huì)自動(dòng)轉(zhuǎn)換數(shù)據(jù)類型寥粹,比如:
不同類型的數(shù)據(jù)進(jìn)行互相運(yùn)算;
對(duì)非布爾值類型的數(shù)據(jù)求布爾值埃元,等涝涤。

1、自動(dòng)轉(zhuǎn)換為布爾值

除了以下6個(gè)值岛杀,其他都是自動(dòng)轉(zhuǎn)為true:

  • undefined
  • null
  • -0
  • +0
  • NaN
  • ''(空字符串)

:

if (!undefined && !null && !0 && !NaN && !''){
    console.log('true');
}
// true

2阔拳、自動(dòng)轉(zhuǎn)換為字符串
字符串的自動(dòng)轉(zhuǎn)換,主要發(fā)生在加法運(yùn)算時(shí)。

'5' + 1 // '51'
'5' + true // "5true"
'5' + {} // "5[object Object]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"

3糊肠、自動(dòng)轉(zhuǎn)換為數(shù)值

當(dāng)JavaScript遇到預(yù)期為數(shù)值的地方辨宠,就會(huì)將參數(shù)值自動(dòng)轉(zhuǎn)換為數(shù)值,轉(zhuǎn)換規(guī)則與“強(qiáng)制轉(zhuǎn)換為數(shù)值”相同货裹。

除了加法運(yùn)算符有可能把運(yùn)算子轉(zhuǎn)為字符串嗤形,其他運(yùn)算符都會(huì)把兩側(cè)的運(yùn)算子自動(dòng)轉(zhuǎn)成數(shù)值。

'5' - '2' // 3
'5' * '2' // 10
true - 1  // 0
false - 1 // -1
'1' - 1   // 0
'5' * []    // 0
false / '5' // 0
'abc' - 1   // NaN

JavaScript的兩個(gè)一元算術(shù)運(yùn)算符也會(huì)把運(yùn)算子自動(dòng)轉(zhuǎn)為數(shù)值弧圆。

+'abc' // NaN
-'abc' // NaN
+true // 1
-false // 0

c. 加法運(yùn)算符的類型轉(zhuǎn)化

加法運(yùn)算符(+)需要特別討論赋兵,因?yàn)樗梢酝瓿蓛煞N運(yùn)算(加法和字符連接),所以不僅涉及到數(shù)據(jù)類型的轉(zhuǎn)換搔预,還涉及到確定運(yùn)算類型霹期。

2、三種情況

  • 運(yùn)算子之中有字符串

則另一個(gè)被轉(zhuǎn)為字符串拯田,然后執(zhí)行字符串連接運(yùn)算历造。

  • 運(yùn)算子都為數(shù)值或布爾值,則執(zhí)行加法運(yùn)算

布爾值轉(zhuǎn)為數(shù)值(true為1船庇,false為0)吭产。

true + 5 // 6 
true + true // 2
  • 運(yùn)算子之中存在對(duì)象

太復(fù)雜,略溢十。

2.3 運(yùn)算符

2.3.1 算數(shù)運(yùn)算符

  • 加法運(yùn)算符(Addition):x + y
    加法運(yùn)算符(+)需要注意的地方是垮刹,它除了用于數(shù)值的相加,還能用于字符串的連接张弛。

  • 減法運(yùn)算符(Subtraction): x - y

  • 乘法運(yùn)算符(Multiplication): x * y

  • 除法運(yùn)算符(Division):x / y

  • 余數(shù)運(yùn)算符(Remainder):x % y

運(yùn)算結(jié)果的正負(fù)號(hào)由第一個(gè)運(yùn)算子的正負(fù)號(hào)決定(有負(fù)數(shù)的話建議先使用絕對(duì)值)

12 % 5 // 2
-1 % 2 // -1
1 % -2 // 1

// 判斷偶數(shù)
function isOdd(n) {
    return Math.abs(n % 2) === 1;
}
  • 自增運(yùn)算符(Increment):++x 或者 x++

  • 自減運(yùn)算符(Decrement):--x 或者 x--

  • 求負(fù)運(yùn)算符(Negate):-x

  • 數(shù)值運(yùn)算符(Convert to number): +x

作用是將任何值轉(zhuǎn)為數(shù)值(與Number函數(shù)作用相同)荒典。

+true // 1
+[] // 0
+{} // NaN

2.3.2 賦值運(yùn)算符

=、 += 吞鸭、 -= 寺董、 *= 、 /= 刻剥、 %= 遮咖、 >>= 、 <<= 造虏、 >>>= 御吞、 &= 、 |= 漓藕、 ^=

2.3.2 比較運(yùn)算符

== 相等
=== 嚴(yán)格相等
!= 不相等
!== 嚴(yán)格不相等
< 小于
<= 小于或等于

大于
= 大于或等于

相等運(yùn)算符(==)比較兩個(gè)“值”是否相等陶珠,嚴(yán)格相等運(yùn)算符(===)比較它們是否為“同一個(gè)值”。
兩者的一個(gè)重要區(qū)別是享钞,如果兩個(gè)值不是同一類型揍诽,嚴(yán)格相等運(yùn)算符(===)直接返回false,而相等運(yùn)算符(==)會(huì)將它們轉(zhuǎn)化成同一個(gè)類型,再用嚴(yán)格相等運(yùn)算符進(jìn)行比較暑脆。

我們先看嚴(yán)格相等運(yùn)算符渠啤。

嚴(yán)格相等運(yùn)算符

1、不同類型的值

如果兩個(gè)值的類型不同添吗,直接返回false沥曹。

2、同一類的原始類型值

同一類型的原始類型的值(數(shù)值根资、字符串架专、布爾值)比較時(shí)同窘,值相同就返回true玄帕,值不同就返回false。

1 === 0x1 // true
  • NaN與任何值都不相等(包括自身)想邦。
  • 正0等于負(fù)0裤纹。

3、同一類的復(fù)合類型值
復(fù)合類型(對(duì)象丧没、數(shù)組鹰椒、函數(shù))的數(shù)據(jù)比較時(shí),是比較它們是否指向同一個(gè)對(duì)象(內(nèi)存地址)呕童。

({}) === {} // false
[] === [] // false
(function (){}) === function (){} // false

var v1 = {};
var v2 = v1;
v1 === v2 // true

4漆际、undefined和null

undefined 和 null 與自身嚴(yán)格相等。

undefined === undefined // true
null === null // true

由于變量聲明后默認(rèn)值是undefined夺饲,因此兩個(gè)只聲明未賦值的變量是相等的奸汇。

var v1;
var v2;
v1 === v2 // true

相等運(yùn)算符

相等運(yùn)算符在比較相同類型的數(shù)據(jù)時(shí),與嚴(yán)格相等運(yùn)算符完全一樣往声。

在比較不同類型的數(shù)據(jù)時(shí)擂找,相等運(yùn)算符會(huì)先將數(shù)據(jù)進(jìn)行類型轉(zhuǎn)換,然后再用嚴(yán)格相等運(yùn)算符比較浩销。類型轉(zhuǎn)換規(guī)則如下:

1贯涎、原始類型的值

原始類型的數(shù)據(jù)會(huì)轉(zhuǎn)換成數(shù)值類型再進(jìn)行比較。

1 == true // true
"true" == true // false
'' == 0 // true
'1' == true  // true

// 注意:字符串轉(zhuǎn)為數(shù)字時(shí)慢洋,省略前置和后置的空格
'\n  123  \t' == 123 // true
'  123  ' == 123 // true
' 123' == 123 // false

2塘雳、對(duì)象與原始類型值比較

對(duì)象(這里指廣義的對(duì)象,包括數(shù)值和函數(shù))與原始類型的值比較時(shí)普筹,對(duì)象轉(zhuǎn)化成原始類型的值败明,再進(jìn)行比較。

[1] == 1 // true
[1] == "1" // true
[1] == true // true

3斑芜、undefined和null

undefined和null與其他類型的值比較時(shí)肩刃,結(jié)果都為false,它們互相比較時(shí)結(jié)果為true。

false == null // false
0 == null // false

undefined == null // true

4盈包、相等運(yùn)算符的缺點(diǎn)
相等運(yùn)算符隱藏的類型轉(zhuǎn)換沸呐,會(huì)帶來(lái)一些違反直覺(jué)的結(jié)果。

'' == '0'           // false
0 == ''             // true
0 == '0'            // true

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true

上面這些表達(dá)式都很容易出錯(cuò)呢燥,因此不要使用相等運(yùn)算符(==)崭添,最好只使用嚴(yán)格相等運(yùn)算符(===)。

布爾運(yùn)算符

布爾運(yùn)算符用于將表達(dá)式轉(zhuǎn)為布爾值叛氨。

1呼渣、取反運(yùn)算符(!)

對(duì)于非布爾值的數(shù)據(jù),取反運(yùn)算符會(huì)自動(dòng)將其轉(zhuǎn)為布爾值寞埠。規(guī)則是屁置,以下六個(gè)值取反后為true,其他值取反后都為false仁连。

undefined
null
false
0(包括+0和-0)
NaN
空字符串("")

兩次取反就是將一個(gè)值轉(zhuǎn)為布爾值的簡(jiǎn)便寫法蓝角。

!!x
// 等同于
Boolean(x)

2、且運(yùn)算符(&&)
“短路”機(jī)制

3饭冬、或運(yùn)算符(||)

4使鹅、三元條件運(yùn)算符( ? :)

"t" ? true : false // true

5、位運(yùn)算符

5.1 簡(jiǎn)介
或運(yùn)算(or)|
與運(yùn)算(or)&
否運(yùn)算(not)~
異或運(yùn)算(xor)?
左移運(yùn)算(left shift)<<
右移運(yùn)算(right shift)>>
帶符號(hào)位的右移運(yùn)算(zero filled right shift)>>>

略昌抠。

其他運(yùn)算符

1患朱、圓括號(hào)運(yùn)算符() 表示求值:

有2種用法:
把表達(dá)式放在圓括號(hào)之中,作用是求值炊苫;
跟在函數(shù)的后面裁厅,作用是調(diào)用函數(shù)。

(2) // 2
    
function f(){return 1;}
(f) // function f(){return 1;}
f() // 1

// 語(yǔ)句沒(méi)有返回值所以不能放在括號(hào)里
(var a =1) // SyntaxError: Unexpected token var

2劝评、void運(yùn)算符 作用是執(zhí)行一個(gè)表達(dá)式姐直,然后返回undefined。

void (0) // undefined

這個(gè)運(yùn)算符主要是用在超級(jí)鏈接中插入代碼蒋畜,目的是返回undefined可以防止網(wǎng)頁(yè)跳轉(zhuǎn)声畏。

javascript:void window.open("http://example.com/")

比如:

<a href="#" onclick="f();return false;">文字</a>

void運(yùn)算符可以取代上面兩種寫法。

<a href="javascript:void(0)" onclick="f();">文字</a>

3姻成、逗號(hào)運(yùn)算符

逗號(hào)運(yùn)算符用于對(duì)兩個(gè)表達(dá)式求值插龄,并返回后一個(gè)表達(dá)式的值。

"a", "b" // "b"

var x = 0;
var y = (x++, 10);
x // 1
y // 10

運(yùn)算順序

運(yùn)算符是有優(yōu)先級(jí)的
圓括號(hào)的優(yōu)先級(jí)最高(建議總是使用圓括號(hào))

左結(jié)合與右結(jié)合
大部分運(yùn)算符是左結(jié)合科展,
少數(shù)是右結(jié)合均牢,最主要的是:=和三元運(yùn)算符(?:)。

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

相當(dāng)于:

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

2.4 數(shù)值

數(shù)字都以64位浮點(diǎn)數(shù)形式儲(chǔ)存才睹。

2.4.1 精度和取值范圍

整數(shù)在絕對(duì)值<=253(Math.pow(2, 53))內(nèi)的都可以精確表示徘跪。
浮點(diǎn)數(shù)取值范圍在21024到2-1024(開(kāi)區(qū)間)之間甘邀。

由于浮點(diǎn)數(shù)不是精確的值,所以涉及小數(shù)的比較和運(yùn)算要特別小心垮庐。

0.1 + 0.2 === 0.3
// false

0.3 / 0.1
// 2.9999999999999996

2.4.2 數(shù)值的表示法

可以用字面形式直接表示松邪,也可以采用科學(xué)計(jì)數(shù)法表示。

123e3 // 123000
123e-3 // 0.123

正常情況下哨查,所有數(shù)值都為十進(jìn)制逗抑。
十六進(jìn)制必須以0x或0X開(kāi)頭。
八進(jìn)制數(shù)必須以0開(kāi)頭(八進(jìn)制很容易造成混亂)寒亥。

2.4.3 特殊數(shù)值

1邮府、零
JavaScript提供零的3種寫法:0、+0溉奕、-0褂傀。它們是等價(jià)的。
但是腐宋,如果正零和負(fù)零分別當(dāng)作分母紊服,它們返回的值是不相等的檀轨。

(1/+0) === (1/-0) // false

因?yàn)槌哉愕玫?Infinity胸竞,除以負(fù)零得到-Infinity,這兩者是不相等的(關(guān)于Infinity詳見(jiàn)后文)参萄。

2卫枝、NaN
NaN表示“非數(shù)字”(Not a Number)。
NaN不等于任何值讹挎,包括它本身校赤。
NaN與任何數(shù)(包括它自己)的運(yùn)算,得到的都是NaN筒溃。

isNaN函數(shù)可以用來(lái)判斷一個(gè)值是否為NaN马篮。
但是,isNaN只對(duì)數(shù)值有效怜奖,如果傳入其他值浑测,會(huì)被先轉(zhuǎn)成數(shù)值。也就是說(shuō)歪玲,isNaN為true的值迁央,有可能不是NaN,而是一個(gè)字符串滥崩。

isNaN("Hello") // true

因此岖圈,使用isNaN之前,最好判斷一下數(shù)據(jù)類型钙皮。

function myIsNaN(value) {
    return typeof value === 'number' && isNaN(value);
}

或者利用NaN是唯一不等于自身的值這個(gè)特點(diǎn)蜂科,進(jìn)行判斷顽决。

function myIsNaN(value) {
    return value !== value;
}

3、Infinity
Infinity表示“無(wú)窮”导匣。除了0除以0得到NaN擎值,其他任意數(shù)除以0,得到Infinity逐抑。

1 / -0 // -Infinity
1 / +0 // Infinity

運(yùn)算結(jié)果超出JavaScript可接受范圍鸠儿,也會(huì)返回?zé)o窮。

JavaScript的數(shù)學(xué)運(yùn)算幾乎沒(méi)有可能拋出錯(cuò)誤厕氨。

isFinite函數(shù)返回一個(gè)布爾值进每,檢查某個(gè)值是否為正常值,而不是Infinity命斧。

isFinite(Infinity) // false
isFinite(NaN) // false

2.4.4 與數(shù)值相關(guān)的全局方法

1田晚、parseInt
將字符串或小數(shù)轉(zhuǎn)化為整數(shù)。字符串頭部空格會(huì)被自動(dòng)去除国葬。一旦遇到不能轉(zhuǎn)化的字符就停止繼續(xù)轉(zhuǎn)化贤徒。
如果字符串的第一個(gè)字符不能轉(zhuǎn)化為數(shù)字(正負(fù)號(hào)除外),返回NaN汇四。

parseInt('   1a23') // 1

parseInt("abc") // NaN
parseInt(".3") // NaN

parseInt還可以接受第二個(gè)參數(shù)(2到36之間)接奈,表示被解析的值的進(jìn)制。這意味著通孽,可以用parseInt方法進(jìn)行進(jìn)制的轉(zhuǎn)換缅帘。

parseInt(1000, 2) // 8

2产弹、parseFloat
將字符串轉(zhuǎn)為浮點(diǎn)數(shù)寒屯。同樣遗契,字符串頭部空格會(huì)被自動(dòng)去除。一旦遇到不能轉(zhuǎn)化的字符就停止繼續(xù)轉(zhuǎn)化行剂。
如果字符串的第一個(gè)字符不能轉(zhuǎn)化為浮點(diǎn)數(shù)秕噪,返回NaN。

parseFloat("   3.14"); // 3.14

parseFloat("a2") // NaN
parseFloat("") // NaN

parseFloat將空字符串轉(zhuǎn)為NaN厚宰。

parseFloat的轉(zhuǎn)換結(jié)果不同于Number函數(shù)腌巾。

parseFloat(true)  // NaN
Number(true) // 1
parseFloat(null) // NaN
Number(null) // 0
parseFloat('') // NaN
Number('') // 0
parseFloat('123.45#') // 123.45
Number('123.45#') // NaN

2.5 字符串

2.5.1 概述

字符串默認(rèn)只能寫在一行內(nèi),如果必須分成多行固阁,可以在每一行的尾部使用反斜杠(ECMAScript 5新添加)壤躲,而且反斜杠的后面必須是換行符,不能有其他字符(比如空格)备燃。

var longString = "Long \
string";

連接運(yùn)算符(+)可以連接多個(gè)單行字符串碉克。

var longString = "Long " + "string";

轉(zhuǎn)義

\n 換行符
\r 回車鍵
\t 制表符
\' 單引號(hào)
\" 雙引號(hào)
\\ 反斜杠

字符串與數(shù)組

字符串可以被視為字符數(shù)組,因此可以使用數(shù)組的方括號(hào)運(yùn)算符并齐。

'hello'[0] // "h"
'hello'[5] // undefined

但是漏麦,實(shí)際上客税,字符串是類似數(shù)組的對(duì)象,且無(wú)法改變字符串之中的單個(gè)字符撕贞。length屬性也是無(wú)法改變的更耻。

var s = 'hello';

delete s[0];
s[1] = 'a';
s.length = 3;
s // "hello"

字符串內(nèi)部的單個(gè)字符無(wú)法改變和增刪,這些操作會(huì)默默地失敗捏膨。字符串的length也無(wú)法改變秧均,但不會(huì)報(bào)錯(cuò)。

字符串也無(wú)法添加新屬性:

var s = "Hello World";
s.x = 123;
s.x // undefined

2.5.2 字符集

JavaScript內(nèi)部所有字符都用Unicode表示号涯。所有字符都可以寫成"\uxxxx"的形式目胡。

var s = '\u00A9';
s // "?"

注意:UTF-16有兩種長(zhǎng)度:對(duì)于U+0000到U+FFFF之間的字符,長(zhǎng)度為16位(即2個(gè)字節(jié))链快;對(duì)于U+10000到U+10FFFF之間的字符誉己,長(zhǎng)度為32位(即4個(gè)字節(jié))。

var s = "\uD834\uDF06"

s // "??"
s.length // 2
s.charAt(0) // ""
s.charCodeAt(0) // 55348

由于JavaScript引擎(ES5)不能自動(dòng)識(shí)別編號(hào)大于0xFFFF的Unicode字符域蜗,導(dǎo)致所有字符串處理函數(shù)遇到這類字符巨双,都會(huì)產(chǎn)生錯(cuò)誤的結(jié)果,所以必須判斷字符是否落在0xD800到0xDFFF這個(gè)區(qū)間霉祸。

下面是能夠正確處理字符串遍歷的函數(shù):

function getSymbols(string) {
  var length = string.length;
  var index = -1;
  var output = [];
  var character;
  var charCode;
  while (++index < length) {
    character = string.charAt(index);
    charCode = character.charCodeAt(0);
    if (charCode >= 0xD800 && charCode <= 0xDBFF) {
      output.push(character + string.charAt(++index));
    } else {
      output.push(character);
    }
  }
  return output;
}

替換(String.prototype.replace)筑累、截取子字符串(String.prototype.substring, String.prototype.slice)等其他字符串操作,都必須做類似的處理脉执。

2.5.3 Base64轉(zhuǎn)碼

window.btoa("Hello World")
// "SGVsbG8gV29ybGQ="
window.atob("SGVsbG8gV29ybGQ=")
// "Hello World"

這兩個(gè)方法不適合非ASCII碼的字符疼阔,瀏覽器會(huì)報(bào)錯(cuò)。

window.btoa('你好')
// InvalidCharacterError: An invalid or illegal character was specified, such as in an XML name.

要將非ASCII碼字符轉(zhuǎn)為Base64編碼半夷,必須中間插入一個(gè)瀏覽器轉(zhuǎn)碼的環(huán)節(jié),再使用這兩個(gè)方法迅细。

function b64Encode( str ) {
    return window.btoa(unescape(encodeURIComponent( str )));
}
 
function b64Decode( str ) {
    return decodeURIComponent(escape(window.atob( str )));
}

// 使用方法
b64Encode('你好') // "5L2g5aW9"
b64Decode('5L2g5aW9') // "你好"

2.6 對(duì)象

2.6.1 概述

所謂對(duì)象巫橄,就是一種無(wú)序的數(shù)據(jù)集合,由若干個(gè)“鍵值對(duì)”(key-value)構(gòu)成茵典。
JavaScript的所有數(shù)據(jù)都可以被視為對(duì)象湘换。

var o = {
    id: 123,
    "na me": "Hello"
};

鍵名加不加引號(hào)都可以。但是统阿,如果鍵名不符合標(biāo)識(shí)名的條件(比如包含數(shù)字彩倚、字母、下劃線以外的字符扶平,或者第一個(gè)字符為數(shù)字)帆离,也不是正整數(shù),則必須加上引號(hào)结澄。

如果一個(gè)屬性的值為函數(shù)哥谷,通常把這個(gè)屬性稱為“方法”岸夯。

2.6.1.1 生成方法

var o1 = {};
var o2 = new Object();
var o3 = Object.create(null);

2.6.1.2 讀取屬性

有兩種方法,一種是使用點(diǎn)運(yùn)算符们妥,還有一種是使用方括號(hào)運(yùn)算符猜扮。

var o = {
    id: "Hello",
    0.7: "World"
};

o.id // "Hello"
o["id"] // "Hello"
o["i" + "d"] // "Hello"
o["0.7"] // "World"
o[0.7] // "World"

注意,如果使用方括號(hào)運(yùn)算符监婶,鍵名必須放在引號(hào)里面旅赢,否則會(huì)被當(dāng)作變量處理。但是惑惶,數(shù)字鍵可以不加引號(hào)鲜漩,因?yàn)闀?huì)被當(dāng)作字符串處理。

2.6.1.3 檢查變量是否聲明

讀取一個(gè)不存在的鍵集惋,會(huì)返回undefined孕似,而不是報(bào)錯(cuò)。
可以使用in運(yùn)算符判斷屬性是否存在(也可以判斷變量是否聲明)刮刑。

"id" in o // true
0.8 in o // false
o in window // true

在瀏覽器環(huán)境喉祭,所有全局變量都是window對(duì)象的屬性。

2.6.1.4 寫入屬性

同樣使用:點(diǎn)運(yùn)算符和方括號(hào)運(yùn)算符雷绢。

o.p = "abc";
o["p"] = "abc";

JavaScript允許屬性的“后綁定”泛烙,也就是說(shuō),你可以在任意時(shí)刻新增屬性翘紊,沒(méi)必要在定義對(duì)象的時(shí)候蔽氨,就定義好屬性。

var o = { p:1 };

// 等價(jià)于
var o = {};
o.p = 1;

2.6.1.5 查看所有屬性(Object.keys)

Object.keys(o);
// ["id", "0.8"]

2.6.1.6 屬性的刪除(delete)

delete o.p // true
o.p // undefined

一旦使用delete命令刪除某個(gè)屬性帆疟,再讀取該屬性就會(huì)返回undefined鹉究,而且Object.keys方法返回的該對(duì)象的所有屬性中,也將不再包括該屬性踪宠。

注意:如果刪除一個(gè)不存在的屬性自赔,delete不報(bào)錯(cuò),而且返回true柳琢。

只有一種情況绍妨,delete命令會(huì)返回false,那就是該屬性存在柬脸,且不得刪除他去。

var o = Object.defineProperty({}, "p", {
        value: 123,
        configurable: false
});

o.p // 123
delete o.p // false

另外,需要注意的是倒堕,delete命令只能刪除對(duì)象本身的屬性灾测,不能刪除繼承的屬性。delete命令也不能刪除var命令聲明的變量涩馆,只能用來(lái)刪除對(duì)象的屬性和方法行施。

2.6.1.7 對(duì)象的引用

如果不同的變量名指向同一個(gè)對(duì)象允坚,那么它們都是這個(gè)對(duì)象的引用,都指向同一個(gè)內(nèi)存地址蛾号。修改其中一個(gè)變量稠项,會(huì)影響到其他所有變量。

var o1 = {};
var o2 = o1;

o1.a = 1;
o2.a // 1

這種引用只局限于對(duì)象鲜结,對(duì)于原始類型的數(shù)據(jù)則是值的拷貝展运。

2.6.1.8 in運(yùn)算符

in運(yùn)算符用于檢查對(duì)象是否包含某個(gè)屬性(注意,檢查的是鍵名精刷,不是鍵值)拗胜。

var o = { p: 1 };
'p' in o // true

該運(yùn)算符對(duì)數(shù)組也適用。

var a = ["hello", "world"];
0 in a // true
'0' in a // true

在JavaScript語(yǔ)言中怒允,所有全局變量都是頂層對(duì)象(瀏覽器環(huán)境的頂層對(duì)象為window)的屬性埂软,因此可以用in運(yùn)算符判斷一個(gè)全局變量是否存在。

if ('x' in window) { return 1; }

in運(yùn)算符對(duì)繼承的屬性也有效纫事。

var o = new Object();
o.hasOwnProperty('toString')  // false
'toString' in o // true

in運(yùn)算符只能用來(lái)檢驗(yàn)可枚舉(enumerable)的屬性勘畔。

2.6.1.9 for...in循環(huán)

var o = {a:1, b:2, c:3};
for (i in o){
    console.log(o[i]);
}

for...in循環(huán)遍歷的是對(duì)象所有可enumberable的屬性,其中不僅包括定義在對(duì)象本身的屬性丽惶,還包括對(duì)象繼承的屬性炫七。

如果只想遍歷對(duì)象本身的屬性,可以使用hasOwnProperty方法做一個(gè)判斷钾唬。

for (var key in person) {
    if (person.hasOwnProperty(key)) {
        console.log(key);
    }
}

2.6.2 類似數(shù)組的對(duì)象

在js中万哪,有些對(duì)象被稱為“類似數(shù)組的對(duì)象”,它們可以使用length屬性抡秆,但是它們并不是數(shù)組奕巍,無(wú)法使用一些數(shù)組的方法。

var a = {
    0:'a',
    1:'b',
    length:2
};
a[0] // 'a'
a.length // 3

變量a就是一個(gè)類似數(shù)組的對(duì)象琅轧,但它無(wú)法使用數(shù)組特有的一些方法伍绳,比如pop和push方法。而且乍桂,length屬性不是動(dòng)態(tài)值。

典型的類似數(shù)組的對(duì)象是:函數(shù)的arguments對(duì)象效床,以及大多數(shù)DOM元素集睹酌,還有字符串

// arguments對(duì)象
function args() { for(var i=0;i<arguments.length;i++) alert(arguments[i]); }
args('a', 'b');

// DOM元素集
var elts = document.getElementsByTagName('h3');

// 字符串
'abc'[1] // 'b'
'abc' instanceof Array // false

通過(guò)函數(shù)的call方法剩檀,可以用slice方法將類似數(shù)組的對(duì)象憋沿,變成真正的數(shù)組

var arr = Array.prototype.slice.call("abc");

遍歷類似數(shù)組的對(duì)象沪猴,可以采用for循環(huán)辐啄,也可以采用數(shù)組的forEach方法采章。

// for循環(huán)
for(var i=0;i<"abc".length;i++){
    console.log(i+'. '+"abc"[i]);
};

// forEach方法
Array.prototype.forEach.call("abc", function (elem, i) {
    console.log(i+'. '+elem);
});

2.6.3 with語(yǔ)句(不建議使用)

with語(yǔ)句的作用是操作同一個(gè)對(duì)象的多個(gè)屬性時(shí),提供一些書寫的方便壶辜。

o.p1 = 1;
o.p2 = 2;
// 等同于
with (o){
    p1 = 1;
    p2 = 2;
}

注意:在with區(qū)塊內(nèi)部依然是全局作用域悯舟。這意味著,如果你要在with語(yǔ)句內(nèi)部砸民,賦值對(duì)象某個(gè)屬性抵怎,這個(gè)屬性必須已經(jīng)存在,否則你就是聲明了一個(gè)全局變量(綁定對(duì)象不明確)岭参。

2.7 數(shù)組

2.7.1 數(shù)組的定義

數(shù)組(array)是按次序排列的一組值反惕,單個(gè)值稱為元素。

  1. 編號(hào)從0開(kāi)始演侯。
  2. 可變長(zhǎng)姿染。可先定義再賦值秒际。
  3. 元素可以是任何類型悬赏。

例如:

var arr = [];
arr[0] = {a:1}; // 對(duì)象
arr[1] = [1,2,3]; // 數(shù)組
arr[2] = function (){return true;}; // 函數(shù)

如果數(shù)組的元素還是數(shù)組,就形成了多維數(shù)組程癌。

var a = [[1,2],[3,4],"x"];
console.log(a[0][0]);
console.log(a[2]);

2.7.2 數(shù)組與對(duì)象的關(guān)系

本質(zhì)上舷嗡,數(shù)組也屬于對(duì)象。

typeof [1,2,3] // "object"

上面代碼表明嵌莉,數(shù)組只是一種特殊的對(duì)象进萄,所以typeof運(yùn)算符返回?cái)?shù)組的類型是object。

數(shù)組是字典結(jié)構(gòu)的一個(gè)變種锐峭,它的鍵是0開(kāi)始的整數(shù)中鼠。

var arr = ['a', 'b', 'c'];
arr['0'] // 'a'
arr[0] // 'a'

上面代碼分別用數(shù)值和字符串作為鍵名,結(jié)果都能讀取數(shù)組沿癞。

需要注意的是援雇,這一條在賦值時(shí)也成立,即如果一個(gè)值可以被轉(zhuǎn)換為整數(shù)椎扬,則以該值為鍵名惫搏,等于以對(duì)應(yīng)的整數(shù)為鍵名。

var a = [];
a[0] = 0;
a['1000'] = 'abc';
console.log(a.length); // 1001

對(duì)于數(shù)字的鍵名蚕涤,不能使用點(diǎn)結(jié)構(gòu)筐赔,所以arr.0的寫法不合法。因此數(shù)組只能用方括號(hào)arr[0]表示揖铜。

2.7.3 length屬性

  • 數(shù)組的length是一個(gè)動(dòng)態(tài)的值茴丰。它是最大鍵值+1.
  • length屬性是可寫的。設(shè)置length可以改變數(shù)組的大小,空位都填充為undefined贿肩。
    如果設(shè)置length為不合法的值峦椰,JavaScript會(huì)報(bào)錯(cuò)。
  • 可以為數(shù)組添加屬性(因?yàn)閿?shù)組本質(zhì)上是對(duì)象)汰规,但這不影響length的值

示例:

var a = [];
a[1] = 'abc';
a['10'] = 'abc'; //a.length是10
a.length=3; //a.length是3
console.log(a); // [undefined, "abc", undefined]
a.id="ddd"; //a.length是3
    
[].length = -1 // RangeError: Invalid array length
[].length = 'abc' // RangeError: Invalid array length

2.7.4 數(shù)組的空位

  • delete命令可以刪除值汤功,形成空位。
    注意:使用delete命令刪除值控轿,不影響length屬性冤竹。

  • 空位通過(guò)空值生成,還是通過(guò)顯式設(shè)為undefined生成茬射,有細(xì)微的差別鹦蠕。

如果通過(guò)空值生成,使用數(shù)組的forEach方法或者for...in結(jié)構(gòu)進(jìn)行遍歷在抛,空位就會(huì)被跳過(guò)钟病。

var a = [0,1,,3,undefined];
delete a[1];
console.log(a.length); // 5
a.forEach(function (x, i) { console.log(x) }) // 0,3,undefined 
for (var i in a){console.log(a[i])} // 0,3,undefined 

2.7.5 in運(yùn)算符,for...in循環(huán)

  • in可以堅(jiān)持是否存在某個(gè)鍵
    檢查某個(gè)鍵是否存在的運(yùn)算符in刚梭,適用于對(duì)象肠阱,也適用于數(shù)組。
  • for-in循環(huán)朴读,可以遍歷數(shù)組的所有元素
    注意:for-in會(huì)遍歷數(shù)組所有的鍵屹徘,即使是非數(shù)字鍵。
  • 還可以用for或while遍歷數(shù)組

示例:

var a = [0,,undefined];
console.log(0 in a); // true
console.log(1 in a); // false
console.log(2 in a); // true
a.id = function (){};
for (var i in a){console.log(a[i])} // 0,undefined,function (){} 
for(var i = 0; i < a.length; i++){console.log(a[i]);} // 0,undefined,undefined 

2.7.6 Array構(gòu)造函數(shù)

數(shù)組還可以使用JavaScript內(nèi)置的Array構(gòu)造函數(shù)創(chuàng)建衅金。

var a = new Array(2);
console.log(a); // [undefined, undefined]
var a = new Array(1,2);
console.log(a); // [1, 2]

2.8 函數(shù)

2.8.1 概述

2.8.1.1 函數(shù)的聲明

1噪伊、function命令聲明函數(shù)

function print(){
    // ...
}

2、函數(shù)表達(dá)式

var print = function (){
    // ...
};

采用函數(shù)表達(dá)式聲明函數(shù)時(shí)氮唯,function命令后面不帶有函數(shù)名鉴吹。
如果加上函數(shù)名,該函數(shù)名只在函數(shù)體內(nèi)部有效惩琉,在函數(shù)體外部無(wú)效豆励。

3、Function構(gòu)造函數(shù)

var add = new Function("x","y","return (x+y)");

最后一個(gè)參數(shù)是add函數(shù)的“函數(shù)體”瞒渠,其他參數(shù)都是add函數(shù)的參數(shù)良蒸。

4、函數(shù)的重復(fù)聲明

重復(fù)聲明同一個(gè)函數(shù)伍玖,則后面的聲明會(huì)覆蓋前面的聲明诚啃。
由于存在函數(shù)名的提升,所以前面的函數(shù)聲明完全是無(wú)效的私沮。

2.8.1.2 圓括號(hào)運(yùn)算符和return語(yǔ)句

調(diào)用函數(shù)時(shí),要使用圓括號(hào)運(yùn)算符。圓括號(hào)之中仔燕,可以加入函數(shù)的參數(shù)造垛。
參數(shù)數(shù)量可以不匹配!

function add(x,y) {
    return x+y;
}

console.log(add(1,2,3)) // 3
console.log(add(1)) // NaN

return語(yǔ)句不是必需的晰搀,如果沒(méi)有的話五辽,該函數(shù)就不返回任何值,或者說(shuō)返回undefined外恕。

函數(shù)調(diào)用自身杆逗,這就是遞歸。

2.8.1.3 第一等公民

JavaScript的函數(shù)與其他數(shù)據(jù)類型處于同等地位鳞疲,可以使用其他數(shù)據(jù)類型的地方就能使用函數(shù)罪郊。
比如,可以把函數(shù)賦值給變量和對(duì)象的屬性尚洽,也可以當(dāng)作參數(shù)傳入其他函數(shù)悔橄,或者作為函數(shù)的結(jié)果返回。
這表示函數(shù)與其他數(shù)據(jù)類型的地方是平等腺毫,所以又稱函數(shù)為第一等公民癣疟。

2.8.1.4 函數(shù)名的提升

JavaScript引擎將函數(shù)名視同變量名,所以采用function命令聲明函數(shù)時(shí)潮酒,整個(gè)函數(shù)會(huì)被提升到代碼頭部睛挚。

f();
var f = function (){ alert("aa";) };

但是,如果采用賦值語(yǔ)句定義函數(shù)就會(huì)報(bào)錯(cuò)急黎,因?yàn)樘嵘闹皇琴x值語(yǔ)句左邊的變量扎狱,函數(shù)并未被提升。

f();
var f = function (){}; // TypeError: undefined is not a function

2.8.1.5 不能在條件語(yǔ)句中聲明函數(shù)

不得在非函數(shù)的代碼塊中聲明函數(shù)叁熔,最常見(jiàn)的情況就是if和try語(yǔ)句委乌。
按照語(yǔ)言規(guī)范,這是不合法的荣回。但是遭贸,實(shí)際情況是各家瀏覽器往往并不報(bào)錯(cuò),能夠運(yùn)行心软。

2.8.1.6 name屬性

大多數(shù)JavaScript引擎支持非標(biāo)準(zhǔn)的name屬性壕吹。該屬性返回緊跟在function關(guān)鍵字之后的那個(gè)函數(shù)名。

function f1() {}
f1.name // 'f1'

var f2 = function () {};
f2.name // ''

2.8.2 函數(shù)作用域

2.8.2.1 定義

Javascript只有兩種作用域:一種是全局作用域删铃,變量在整個(gè)程序中一直存在耳贬;另一種是函數(shù)作用域,變量只在函數(shù)內(nèi)部存在猎唁。

函數(shù)內(nèi)部定義的變量咒劲,會(huì)在該作用域內(nèi)覆蓋同名全局變量。

var w = 1; 
var w2 = 1;
(function f(){
   w=2;
   var w2 = 2;
   var n = 1;
})();
console.log(w); // 2
console.log(w2); // 1
console.log(n); // ReferenceError: n is not defined

2.8.2.2 函數(shù)內(nèi)部的變量提升

與全局作用域一樣,函數(shù)作用域內(nèi)部也會(huì)產(chǎn)生“變量提升”現(xiàn)象腐魂。var命令聲明的變量帐偎,不管在什么位置,變量聲明都會(huì)被提升到函數(shù)體的頭部蛔屹。

2.8.3 參數(shù)

2.8.3.1 概述

函數(shù)可以定義參數(shù)削樊。
函數(shù)對(duì)象的length屬性,返回函數(shù)定義中參數(shù)的個(gè)數(shù)兔毒。

function f(a,b) {}
f.length // 2

2.8.3.2 參數(shù)的省略

函數(shù)調(diào)用時(shí)漫贞,提供多少參數(shù)都不會(huì)報(bào)錯(cuò)。被省略的參數(shù)的值就變?yōu)閡ndefined育叁。多的廢棄迅脐。
沒(méi)有辦法只省略靠前的參數(shù),想那樣只有顯式傳入undefined擂红。

f(undefined,1) 

2.8.3.3 默認(rèn)值

如果要為參數(shù)設(shè)置默認(rèn)值仪际,可以使用方法:

function f(a){
    (a !== undefined && a != null)?(a = a):(a = 1);
    return a;
}
console.log(f('')); // ""
console.log(f(0)); // 0
console.log(f()); // 1
console.log(f(null)); // 1

因?yàn)閡ndefined、0昵骤、空字符树碱、null等的布爾值都是false。

2.8.3.4 傳值方式

js的函數(shù)參數(shù)傳遞方式是值傳遞变秦,這意味著成榜,在函數(shù)體內(nèi)修改參數(shù)值,不會(huì)影響到函數(shù)外部蹦玫。
但是:對(duì)于復(fù)合類型的變量來(lái)說(shuō)赎婚,屬性值是通過(guò)地址讀取的。所以在函數(shù)體內(nèi)修改復(fù)合類型變量的屬性值樱溉,會(huì)影響到函數(shù)外部挣输。

var o = { p:1 };
function f(obj){
    obj.p = 2;
}
f(o);
o.p // 2

var a = [1,2,3];
function f(a){
    a[0]=4;
}
f(a);
a // [4,2,3]

如果需要對(duì)某個(gè)變量達(dá)到按址傳遞的效果,可以將它寫成全局對(duì)象的屬性福贞。

var a = 1;
var b = 2;
function f(x,y){
    x *= 10;
    window[y] *= 10;
}
f(a,'b'); // 注意:第二個(gè)參數(shù)不能是b撩嚼,這樣的話函數(shù)f內(nèi)會(huì)去找window["2"]這個(gè)屬性。
console.log(a); // 1
console.log(b); // 20

2.8.3.5 同名參數(shù)

如果有同名的參數(shù)挖帘,則取最后出現(xiàn)的那個(gè)值完丽。
但是用arguments可以取到正確的參數(shù)。

f(1,2);
function f(a, a){
    console.log(a+a); //4
    console.log(arguments[0] + arguments[1]); //3
}

2.8.3.6 arguments對(duì)象

  • arguments可以在函數(shù)體內(nèi)部讀取所有參數(shù)
    也可設(shè)置拇舀,嚴(yán)格模式不允許這種用法逻族。
  • arguments對(duì)象的length屬性,表示函數(shù)調(diào)用時(shí)到底帶幾個(gè)參數(shù)
  • arguments對(duì)象的callee屬性骄崩,返回它所對(duì)應(yīng)的原函數(shù)
    (注意:不是那個(gè)指向函數(shù)的變量)聘鳞。

示例:

var f = function f2(a) {
   console.log(arguments[0]); // a
   console.log(arguments[1]); // b
   console.log(arguments.length); // 3
   console.log(arguments.callee === f); // true
   console.log(arguments.callee === f2); // true
};
f("a","b","c");

2.8.4 函數(shù)的其他知識(shí)點(diǎn)

2.8.4.1 閉包

閉包是函數(shù)與其生成時(shí)所在的作用域?qū)ο蟮囊环N結(jié)合薄辅。

閉包可以讀取函數(shù)內(nèi)部變量,還可以使得內(nèi)部變量記住上一次調(diào)用時(shí)的運(yùn)算結(jié)果搁痛。

function f(start) {
    return function () { 
        return start++;
    }
}
var inc = f(5);
console.log(inc());  // 5
console.log(inc());  // 6
console.log(inc());  // 7

2.8.4.2 立即調(diào)用的函數(shù)表達(dá)式(IIFE)

(function(){ /* code */ }()); 
// 或者
(function(){ /* code */ })();

這兩種寫法都是以圓括號(hào)開(kāi)頭长搀,引擎就會(huì)認(rèn)為后面跟的是一個(gè)表示式,而不是函數(shù)定義鸡典。

2.8.5 eval命令

eval命令的作用是,將字符串當(dāng)作語(yǔ)句執(zhí)行枪芒。
放在eval中的字符串彻况,應(yīng)該有獨(dú)自存在的意義,不能用來(lái)與eval以外的命令配合使用舅踪。

eval('var a = 1;');
eval('return;'); //報(bào)錯(cuò)

2.9 錯(cuò)誤處理機(jī)制

2.9.1 Error對(duì)象js

一旦發(fā)生錯(cuò)誤纽甘,js引擎會(huì)拋出一個(gè)Error對(duì)象的實(shí)例,然后程序就此中斷抽碌。

Error對(duì)象有3個(gè)基本的屬性:name悍赢、message、stack货徙。

(function catchit() {
   try {
      throw new Error('出錯(cuò)了.'); // Error
   } catch(e) {
      console.log(e.name); // Error
      console.log(e.message); //出錯(cuò)了
      console.log(e.stack); // print stack trace
   }
})();

2.9.2 JavaScript的原生錯(cuò)誤類型

Error對(duì)象是最一般的錯(cuò)誤類型左权,還存在Error的6個(gè)派生對(duì)象。

  • SyntaxError是解析代碼時(shí)發(fā)生的語(yǔ)法錯(cuò)誤痴颊。
  • ReferenceError是引用一個(gè)不存在的變量時(shí)發(fā)生的錯(cuò)誤赏迟。
  • TypeError是變量或參數(shù)不是預(yù)期類型時(shí)發(fā)生的錯(cuò)誤。
    比如蠢棱,對(duì)字符串锌杀、布爾值、數(shù)值等原始類型的值使用new命令泻仙。因?yàn)閚ew命令的參數(shù)應(yīng)該是一個(gè)構(gòu)造函數(shù)糕再。
  • RangeError是當(dāng)一個(gè)值超出有效范圍時(shí)發(fā)生的錯(cuò)誤。
    主要有:一是數(shù)組長(zhǎng)度為負(fù)數(shù)玉转,二是Number對(duì)象的方法參數(shù)超出范圍
  • URIError是URI相關(guān)函數(shù)的參數(shù)不正確時(shí)拋出的錯(cuò)誤突想,主要涉及encodeURI()、decodeURI()冤吨、encodeURIComponent()蒿柳、decodeURIComponent()、escape()和unescape()這六個(gè)函數(shù)漩蟆。
  • EvalError是eval函數(shù)沒(méi)有被正確執(zhí)行時(shí)垒探,會(huì)拋出EvalError錯(cuò)誤。

示例:

var 1a; // SyntaxError 變量名錯(cuò)誤
new Array(-1) // RangeError  數(shù)組長(zhǎng)度為負(fù)
new 123 // TypeError 123不是函數(shù)
decodeURI('%2') // URIError

2.9.3 自定義錯(cuò)誤

function UserError(message) {
   this.message = message || "默認(rèn)信息";
   this.name = "UserError";
}
UserError.prototype = new Error();
UserError.prototype.constructor = UserError;

自定義一個(gè)錯(cuò)誤對(duì)象UserError怠李,讓它繼承Error對(duì)象圾叼。然:

new UserError("這是自定義的錯(cuò)誤蛤克!");

2.9.4 throw語(yǔ)句

throw語(yǔ)句的作用是中斷程序執(zhí)行,拋出一個(gè)錯(cuò)誤夷蚊。它接受一個(gè)表達(dá)式作為參數(shù)构挤。

throw "Error!"; 

2.9.5 try...catch結(jié)構(gòu)和finally代碼塊

try {
    throw new Error('出錯(cuò)了!');
} catch (e) {
    console.log(e.name + ": " + e.message); 
    console.log(e.stack);  
}finally {
    console.log('無(wú)論是否出錯(cuò)都執(zhí)行');
}

甚至可以省略catch代碼塊惕鼓,只使用finally代碼塊筋现。

try {
   ....
} finally {
   console.log('無(wú)論是否出錯(cuò)都執(zhí)行');
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市箱歧,隨后出現(xiàn)的幾起案子矾飞,更是在濱河造成了極大的恐慌,老刑警劉巖呀邢,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件洒沦,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡价淌,警方通過(guò)查閱死者的電腦和手機(jī)申眼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蝉衣,“玉大人括尸,你說(shuō)我怎么就攤上這事÷蚰耍” “怎么了姻氨?”我有些...
    開(kāi)封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)剪验。 經(jīng)常有香客問(wèn)我肴焊,道長(zhǎng),這世上最難降的妖魔是什么功戚? 我笑而不...
    開(kāi)封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任娶眷,我火速辦了婚禮,結(jié)果婚禮上啸臀,老公的妹妹穿的比我還像新娘届宠。我一直安慰自己,他們只是感情好乘粒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布豌注。 她就那樣靜靜地躺著,像睡著了一般灯萍。 火紅的嫁衣襯著肌膚如雪轧铁。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天旦棉,我揣著相機(jī)與錄音齿风,去河邊找鬼药薯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛救斑,可吹牛的內(nèi)容都是我干的童本。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼脸候,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼穷娱!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起纪他,我...
    開(kāi)封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鄙煤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后茶袒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡凉馆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年薪寓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澜共。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡向叉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嗦董,到底是詐尸還是另有隱情母谎,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布京革,位于F島的核電站奇唤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏匹摇。R本人自食惡果不足惜咬扇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望廊勃。 院中可真熱鬧懈贺,春花似錦、人聲如沸坡垫。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)冰悠。三九已至堡妒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間屿脐,已是汗流浹背涕蚤。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工宪卿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人万栅。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓佑钾,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親烦粒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子休溶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 第5章 引用類型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,233評(píng)論 0 4
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,516評(píng)論 1 51
  • 01 大家先看看下面一張圖兽掰! 有何感想呢?這個(gè)共享單車到底是怎么了呢徒役?落得如此下場(chǎng)孽尽。估計(jì),只要生活在有共享單車的城...
    朱團(tuán)輝閱讀 338評(píng)論 0 5
  • 因?yàn)槁?tīng)了壹心理學(xué)院的一期心理學(xué)課程忧勿,了解了紀(jì)元老師與他的自律幫杉女。在心理學(xué)課程中,講到如何早起這件事上鸳吸,紀(jì)老師的想法...
    彼得潘王國(guó)閱讀 1,108評(píng)論 0 0
  • 對(duì)于風(fēng)水熏挎,我還是有些相信的。剛搬了辦公室晌砾,又要搬坎拐,還是有些不舍的。 他相信的風(fēng)水其實(shí)我是有些疑問(wèn)的养匈,不過(guò)千...
    蕓飄燃閱讀 215評(píng)論 0 0