1. 程式人生 > >chapter1.2、JS基礎語法

chapter1.2、JS基礎語法

JS基礎語法

註釋

/**
 * 多行註釋
 */

//單行註釋

常量和變數

識別符號

識別符號必須是字母、下劃線、美元符號$和數字,但必須是字母、下劃線、美元符號開頭,依然是不能數字開頭。
識別符號區分大小寫。

宣告

var 宣告一個變數
let 宣告一個塊作用域中的區域性變數
const  宣告一個常量
JS中的變數宣告和初始化是可以分開的

var a //宣告變數,此時a為undefined
a = 100 //賦值
let b //宣告變數,ES6開始支援,宣告一個塊作用域中的區域性變數
b = 200
const  c = 300 //宣告常量,必須賦值,不能只寫const,之後不能再改
z = 6 //不規範的初始化,不推薦,在嚴格模式下,會產生異常,在賦值前不能引用,一旦這樣賦值就是全域性作用域 console.log(3,a,b,c,z)

var會把變數提升到當前全域性或函式作用域。

function hello(){
    var a 
    a = 100
}
console.log(a) // 未宣告變數,異常
// a = 200 // 不能提升宣告
// let a = 200 //不能提升宣告

console.log(b) // 不是未定義報錯,而是返回undefined
var b = 200 // 後執行賦值, var 宣告提升hoisting

對於函式,只有函式宣告會被提升到頂部,而不包括函式表示式。

/* 函式宣告 */
foo() // 宣告提升

function foo(){
    console.log("bar")
}

/* 函式表示式 */
baz(); // 不進行宣告提升,報TypEerror : baz is not a funtion 

var baz = function() {
    console.log("bar2")
}

 

常量和變數的選擇
如果明確知道一個識別符號定義後不再修改,應該儘量宣告成const常量,減少被修改的風險,減少Bug。

資料型別

number 數值型,包括整型和浮點型

boolean 布林型,true和false

string 字串

null 只有一個值null

undefined 變數宣告未賦值的,物件為定義的屬性

symbol ES6 新引入的型別

object 型別 是以上的基本型別的符合型別,是容器

ES是動態語言,弱型別語言

雖然先宣告變數,但是變數可以重新賦值任何型別

//型別轉換
console.log("========string++++++++")
console.log(a = 3 + "hello", typeof(a)) //3hello string
console.log(a = null + "hello", typeof(a)) //nullhello string
console.log(a = undefined + "hello", typeof(a)) //undefinedhello string
console.log(a = true + "hello", typeof(a)) //truehello string

console.log("+++++++++number=======")
console.log(a = null + 8, typeof(a)) //8 'number'
console.log(a = undefined + 8, typeof(a)) //NaN 'number' undefined沒法轉換成對應的數字
console.log(a = true + 8, typeof(a)) //8 'number'
console.log(a = false + 8, typeof(a)) //8 'number'

console.log("+++++++++boolean=======")
console.log(a = null + true, typeof(a)) // 1 'number'
console.log(a = null + false, typeof(a)) //0 'number'
console.log(a = undefined + true, typeof(a)) //NaN 'number'
console.log(a = undefined + false, typeof(a)) //NaN 'number' //not a number
console.log(a = null & true, typeof(a)) // 0 'number' // & 位與
console.log(a = undefined & true, typeof(a)) // 0 'number'

//短路
console.log(a = null && true, typeof(a)) // 邏輯運算子, null直接就是false短路,返回null 'object'
console.log(a = false && null, typeof(a)) // 邏輯運算子, false直接false短路,返回false "boolean"
console.log(a = false && "hello", typeof(a)) // 返回false "boolean"
console.log(a = true && "world", typeof(a)) // 返回world string
console.log(a = true && "", typeof(a)) // 返回 string 空字串

//null
console.log("+++++++++null=======")
console.log(a = null + undefined, typeof(a)) // NaN 'number'

弱型別語言會隱式型別轉換,不需要強制型別轉換。

NaN,即Not a Number,轉換數字失敗。它和任何值都不等,和自己也不等,只能使用Number.isNaN(NaN)

總結:
遇到字串,加號就是拼接字串,所有非字串隱式轉換為字串。

如果沒有字串,加號把其他所有型別都當數字處理,非數字型別隱式轉換為數字。undefined特殊,因為它都沒有定義值,所以轉換數字失敗得到一個特殊值NaN。

&& and ,|| or , ~ 非

如果運算子是邏輯運算子,短路符,返回就是短路時的型別。沒有隱式轉換。

除非你十分明確,否則不要依賴隱式轉換。寫程式碼的時候,往往為了程式的健壯,請顯式轉換。

注意:以上的原則不要死記,忘了就實驗,或者顯示的型別轉換

字串

將一個值使用' 單引號或者 " 雙引號 引用起來就是字串

ES6提供了反引號定義一個字串,可以支援多行,還支援插值。

let a = "abc"
let b = "12138"
let c = `line1
    line2
    line3
`//多行
console.log(c)
//插值,要在反引號字元中,python3.6支援
let name = "jack", age = 101
console.log(`Hi,my name is ${name}. I'm ${age}`)

 轉義字元

 

\0   Null位元組,空字元
\b   退格符
\f   換頁符
\n   換行符
\r   回車符
\t   Tab (製表符)
\v   垂直製表符
\'   單引號
\"   雙引號
\   反斜槓字元(\)
\XXX   由從0到377最多三位八進位制數XXX表示的 Latin-1 字元。例如,\251是版權符號的八進位制序列
\xXX    由從00和FF的兩位十六進位制數字XX表示的Latin-1字元。例如,\xA9是版權符號的十六進位制序列
\uXXXX    由四位十六進位制數字XXXX表示的Unicode字元。例如,\u00A9是版權符號的Unicode序列。見Unicode escape sequences (Unicode 轉義字元)
\u{XXXXX}    Unicode程式碼點 (code point) 轉義字元。例如,\u{2F804} 相當於Unicode轉義字元\uD87E\uDC04的簡寫

字串操作方法

與python類似

let name = 'Riper'
console.log(name.charAt(2)) // p
console.log(name[2]) // p
console.log(name.toUpperCase()) // RIPER
console.log(name.concat('.com')) // Riper.com
console.log(name.slice(2)) // 切片,支援負索引 per
console.log(name.slice(2,5)) // per
console.log(name.slice(-2, -1)) // e
console.log(name.slice(-2)) // er
let url = "www.riper.com"
console.log(url.split('.')) // [ 'www', 'riper', 'com' ]
console.log(url.substr(4,3)) // 返回子串從何處開始,取多長 rip
console.log(url.substring(7,12)) // 返回子串,從何處開始,到什麼為止 er.co
let s = 'riper.tert'
console.log(s.indexOf('er')) // 3
console.log(s.indexOf('er', 4)) // 7
console.log(s.replace('.tert', '.com')) // 替換完直接輸出s
s = ' \triper com \r\n'
console.log(s.trim()) // 去除兩端的空白字元。trimLeft、trimRight是非標函式,少用

數值型number

在JS中,資料均為雙精度浮點型範圍只能在 -(2^53 -1) 和 2^53 -1之間,整型也不例外。
數字型別還有三種符號值:+Infinity(正無窮)、-Infinity(負無窮)和 NaN (not-a-number非數字)。
二進位制0b0010、0B110。
八進位制0755。注意0855,將被認作十進位制,因為8不在八進位制中。ES6中最好使用0o字首表示八進位制。
十六進位制0xAA、0Xff。
指數表示1E3(1000),2e-2(0.02)

常量屬性

var biggestNum = Number.MAX_VALUE; // 最大 1.7976931348623157e+308
var smallestNum = Number.MIN_VALUE; //最小 5e-324
var infiniteNum = Number.POSITIVE_INFINITY; // +Infinity(正無窮)
var negInfiniteNum = Number.NEGATIVE_INFINITY; // -Infinity(負無窮)
var notANum = Number.NaN; // NaN (not-a-number非數字)

console.log(biggestNum,smallestNum,infiniteNum,negInfiniteNum,notANum)

數字的方法

方法 描述
Number.parseFloat()   把字串引數解析成浮點數,和全域性方法 parseFloat() 作用一致
Number.parseInt()   把字串解析成特定基數對應的整型數字,和全域性方法 parseInt() 作用一致
Number.isFinite()   判斷傳遞的值是否為有限數字
Number.isInteger()   判斷傳遞的值是否為整數
Number.isNaN()   判斷傳遞的值是否為 NaN

console.log( a = Number.parseInt("123d4e"), typeof(a)) // 123 "number"
console.log( a = Number.parseFloat("2.2"), typeof(a)) // 2.2 "number"
console.log( a = Number.isFinite(Number.NEGATIVE_INFINITY), typeof(a)) // false "boolean"

內建數學物件Math

Math提供了絕對值、對數指數運算、三角函式運算、最大值、最小值、隨機數、開方等運算函式,提供了PI值

console.log(Math.PI) // 3.141592653589793
console.log(Math.abs(-1)) // 1
console.log(Math.log2(32)) // 5
console.log(Math.sqrt(9)) // 3
console.log(Math.random()) // (0, 1)之間的開區間 0.36634456552786165

運算子

算數運算子

+ - * / %

console.log(1/2) // 0.5自然除
console.log(1/0) // 無異常,返回無窮
console.log(5 % 3) // 2
console.log(parseInt(1/2)) // 0 取整,除法四捨五入
console.log(parseInt(3/2)) // 1 
console.log(parseInt("5/10")) // 5 字串不識別運算子。。
console.log(Math.floor(3/2)) // 1 向下
console.log(Math.ceil(3/2)) // 2 向上
console.log(Math.round(3/2)) // 2 四捨五入
console.log(Math.round(1/2)) // 1

 ++ 和 --

單目運算子,代表變數的自增,自減

i++ 先用再加 ,使用後再自增加1

++i i先自增,在使用i

++不如棧,效率比 i += 1 高,但是大部分解釋語言在解釋時會優化

let i = 0
let a = i++
console.log(a, i) // 0 1
console.log(a,i++) // 0 1
a = ++i
console.log(a, ++i) // 3 4

C,C++,Java 的題目:

i = 0;
let a = ++i+i+++i+++i; //等價於 let a = ++i + i++ + i++ + i
console.log(a); // 7

單目運算子優先順序高於雙目運算子,單目是指運算的單位只有一位,比如++,雙目是兩位,比如+

比較運算子

邏輯運算子 注意短路,將經常判斷的往前放

===   恆等,推薦使用,出於安全性考慮,儘量使用,必須完全相等
!==   嚴格比較,必須完全不等

console.log(100 > '200') // false
console.log(300 > '200') // true
console.log(300 > '2000') // false
console.log(3000 > '2a') // false
console.log('3000' > '2000') // true
// 寬鬆比較
console.log(300 == '300') // true
console.log('200' == '200') // true
// 嚴格比較 ===
console.log(300 === '300') // false
console.log('200' === '200') // true

寬鬆比較會引起隱式型別轉換,不好控制。

不要把不同的型別進行相比,麼有意義。

建議使用嚴格比較,=== ,!==

邏輯運算子

&& || !與,或,非

console.log(0b10 && 0b01) // 1
console.log(0b10 || 0b01) // 2
console.log(!0b01, !0b00) // false true

支援短路,注意將經常進行比較的往前放

位運算

&  |  ^  ~   <<   >>  位與、位或、異或、取反、左移、右移,和Python一樣

console.log((0b0111 & 0b0101).toString(2)) // 101
console.log((0b0111 | 0b0101).toString(2)) // 111
console.log((0b0111 ^ 0b0101).toString(2)) // 10
console.log(~0b0111, 0b0101>>1, 0b0101<<1) // -8 2 10

三元運算子

// 條件表示式?真值:假值
// 等價於簡單的if...else結構:
// if (條件表示式) {
// 真值
// }
// else {
// 假值
// }

console.log(a = 100>200 ? "true": "false") // false
if(100>200){
    var a = "ture1"
}
else{
    var a = "false1"
}
console.log(a) // false1

三元運算子不要寫兩個以上,容易出錯

逗號操作符

JS執行多個表示式寫在一起

let a = 4+5, b = true, c=a > 20 ?'t':'f'
console.log(a) //9
console.log(c) //f

function test() {
    return a++, ++a, a++
}
console.log(test()) // 11
console.log(a) // 12

s = (a=10, b=100, c = a > b ? "T": "F")
console.log(s)

逗號優先順序比等號還低,逗號表示式等於最後一次計算的值,

每一個表示式都有值,賦值表示式就是最後計算的值,逗號表示式就是最後的一個值

其他

instanceof   判斷是否屬於指定型別
typeof   返回型別字串
delete   delete操作符, 刪除一個物件(an object)或一個物件的屬性(an object's property)或者一個數組中某一個鍵值(an element at a specified index in an array)。
in   如果指定的屬性在物件內,則返回true

console.log("a" instanceof String) //false
console.log(1 instanceof Number) // false

a = new String("b")
console.log(a instanceof String) //true
console.log(new Number(1) instanceof Number) // true
console.log(a instanceof Object) //true

console.log(typeof('a')) //string
console.log(typeof 'a') //string
console.log(typeof a) //object

instanceof 要求必須明確使用型別定義變數,就是物件必須是new關鍵字宣告建立的。它可以用於繼承關係的判斷。

typeof就是返回物件的型別字串。

delete 刪除物件、屬性、陣列元素

x = 42;
var y = 43;
let z = 60;
myobj = new Number();
myobj.h = 4; // create property h
console.log(delete x); // returns true (can delete if declared implicitly)
console.log(delete y); // returns false (cannot delete if declared with var)
console.log(delete z); // returns false
console.log(delete Math.PI); // returns false (cannot delete predefined properties)
console.log(delete myobj.h); // returns true (can delete user-defined properties)
console.log(delete myobj); // returns true (can delete if declared implicitly)
console.log('~~~~~~~~~~~~~~~~~~~~')

var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
for(var i=0;i<trees.length;i++)
console.log(trees[i])
console.log('==================')
delete trees[3]; // 陣列中元素被刪除,但空著的位置是undefined
for(var i=0;i<trees.length;i++)
console.log(trees[i])

in判斷的是屬性是否在物件內

let trees = new Array("redwood", "bay", "cedar", "oak", "maple");
console.log(0 in trees); // returns true ,0在陣列物件的index中
console.log(3 in trees); // returns true ,3在陣列物件的index中
console.log(6 in trees); // returns false,6不在陣列物件的index中
console.log("bay" in trees); // return false,bay不是屬性,它是值
console.log("length" in trees); // returns true,length是物件的屬性
console.log('~~~~~~~~~~~~~~~~~~~~')
delete trees[3];
console.log(3 in trees); // return false
for(var i=0;i<trees.length;i++)
console.log(trees[i]);
console.log('~~~~~~~~~~~~~~~~~~~~')

// Custom objects
let mycar = {
color: "red",
year: 1998
};
console.log("color" in mycar); // returns true
console.log("model" in mycar); // returns false
console.log('year' in mycar) // true

運算子優先順序

記不住,就多用括號

表示式

基本表示式,和python差不多

解析式也和python相似,但在ES6中非標,不推薦使用

生成器可以使用生成器函式,ES6開始支援

var和let定義的屬性不可以刪除,但是new的類和類下建立的類的屬性可以,直接賦值的也可以刪除

a