摘要:由于網景公司希望能在靜態頁面上添加一些動態效果,于是叫這哥們在兩周之內設計出了語言。所以簡單說來就是,是一種語言標準,而是網景公司對標準的一種實現。
JavaScript基礎拾遺
為啥說JavaScript的基礎study notes by Tingting
在平時開發時,我們更多的是在寫PHP的邏輯層,但是在寫后臺時多多少少會寫一寫JavaScript的代碼,有時候我們就會遇到對js的字符串、數組、對象搞不清咋么去處理的問題,畢竟我們是Phper,對js的語法和特性并不是那么了解,更多的時候遇到問題都是去百度,然后解決掉了下一次又遇到又去百度,卻不知道為啥是這樣寫,所以就有了這次分享。
JavaScript歷史(一嘴帶過的歷史)在上個世紀的1995年,當時的網景公司正憑借其Navigator瀏覽器成為Web時代開啟時最著名的第一代互聯網公司。
由于網景公司希望能在靜態HTML頁面上添加一些動態效果,于是叫Brendan Eich這哥們在兩周之內設計出了JavaScript語言。你沒看錯,這哥們只用了10天時間。
為什么起名叫JavaScript?原因是當時Java語言非常紅火,所以網景公司希望借Java的名氣來推廣,但事實上JavaScript除了語法上有點像Java,其他部分基本上沒啥關系。
JavaScript和ECMAScript的關系因為網景開發了JavaScript,一年后微軟又模仿JavaScript開發了JScript,為了讓JavaScript成為全球標準,幾個公司聯合ECMA(European Computer Manufacturers Association)組織定制了JavaScript語言的標準,被稱為ECMAScript標準。
所以簡單說來就是,ECMAScript是一種語言標準,而JavaScript是網景公司對ECMAScript標準的一種實現。
目前我們所使用的js語法基本上都是對ECMAScript5.1(ES5)的實現,而現在在前端圈比較流行的ES6(ECMAScript2015)、ES7(ECMAScript2016)就是JavaScript的下一代標準和下幾代標準了,目前瀏覽器對ES6的語法并不是完全支持的,前端圈現在更多的是在Webpack這種打包構建工具中使用,在發布生產代碼或者開發運行時將ES6的語法編譯成瀏覽器兼容的ES5(JavaScript)的語法,如果感興趣看一看看阮一峰的ECMAScript 6 入門,ES6中有很多好玩的語法糖,比如箭頭函數、模板字符串等等。
基礎語法 關于分號JavaScript的語法和PHP語言類似,每個語句以;結束,語句塊用{...}。但是,JavaScript并不強制要求在每個語句的結尾加;,瀏覽器中負責執行JavaScript代碼的引擎會自動在每個語句的結尾補上;。
現在在前端圈因為大量像webpack這種構建工具的使用,反而更推薦不要去加;,因為構建工具在編譯壓縮代碼時會自動給該加的地方加上,所以加不加分號的問題還是看個人習慣,像我們寫PHP的同學可能更習慣加分號。
加不加分號沒有絕對的約束,當然如果你致力于成為一名全棧工程師,比如你在寫Vue組件化時,就更應該去遵守前端規范的約定,不去加分號。
賦值var a = 1 var username = "saboran" var isOk = true
ES6中的let、const和var的對比(可以詳細講一下或者在瀏覽器的console里執行一下參考代碼)
let和const都是es5,es6新版本的js語言規范出來的定義,在這以前定義一個變量只能用var。let和const都是為了彌補var的一些缺陷而新設計出來的。
簡單來說是:let修復了var的作用域的一些bug,變的更加好用。let是更好的var。var的作用域是函數作用域,而let是塊級別(大括號括起來的內容),const聲明的變量只可以在聲明時賦值,不可隨意修改,這是最大的特點。
舉例說明let和var的區別
// 當定義的變量在函數之外時,二者作用域都是全局,并無區別 let name = "Tom" var age = 18 // 當定義的變量位于函數內部時,二者的作用域都是函數內部,也沒有區別 function makeCake(){ let shape = "心型" var size = 8 } // 不同點,let的作用域在塊內,而var并無約束 // 測試let的作用域 function testLet(){ for(let i=0; i < 10; i++){ // todo something } // 此處的console.log的結果是報錯,報錯內容是 i is not defined // 原因就是let 定義的變量的作用域是在塊之間,在這個例子中let定義的i的作用域僅僅在這個for循環中,所以在for循環外部調用i會報錯 console.log(i) } // 測試var的作用域 function testVar(){ for(var i=0; i < 10; i++){ // todo something } // 這里console.log的結果就為10,因為var定義的變量i作用域是在函數內部,當執行完for循環,i自增后便是10. // 這也就是var定義變量不好的一點,我們定義i的本意就應該是只在for循環中生效的 console.log(i) }代碼注釋
js的注釋和PHP一樣有兩種,一種行注釋使用雙斜線//,另一種是塊注釋使用/****/
// 這是變量a的注釋 var a = 100 /** * 這是函數test的塊注釋 */ function test(){ }數據類型和變量
在JavaScript中定義了以下幾種數據類型:
Number(數值型)
布爾值
null
undefined
字符串
數組
對象
簡單說前四種類型和運算符Number
JavaScript不區分整數和浮點數,統一用Number表示,以下都是合法的Number類型:
123 // 整數123 0.456 // 浮點數0.456 1.2345e3 // 科學計數法表示1.2345x1000,等同于1234.5 -99 // 負數 NaN // NaN表示Not a Number,當無法計算結果時用NaN表示 Infinity // Infinity表示無限大,當數值超過了JavaScript的Number所能表示的最大值時,就表示為Infinity
四則運算
1 + 2 // 3 (1 + 2) * 5 / 2 // 7.5 2 / 0 // Infinity 0 / 0 // NaN 10 % 3 // 1 取模(取余)
布爾值
布爾值和布爾代數的表示完全一致,一個布爾值只有true、false兩種值,要么是true,要么是false,可以直接用true、false表示布爾值。
js的與或非運算和PHP語法基本一致
與運算
true && true; // 這個&&語句計算結果為true true && false; // 這個&&語句計算結果為false false && true && false; // 這個&&語句計算結果為false
或運算
false || false; // 這個||語句計算結果為false true || false; // 這個||語句計算結果為true false || true || false; // 這個||語句計算結果為true
非運算(取反)
! true; // 結果為false ! false; // 結果為true ! (2 > 5); // 結果為true
null和undefined
null表示一個“空”的值,它和0以及空字符串""不同,0是一個數值,""表示長度為0的字符串,而null表示“空”,即沒有值。
在JavaScript中,還有一個和null類似的undefined,它表示“未定義”。
JavaScript的設計者希望用null表示一個空的值,而undefined表示值未定義。事實上,大多數情況下,我們都應該用null。undefined僅僅在判斷函數參數是否傳遞的情況下才有用。
比較運算符
比較運算符常用的無非是大于、小于、大于等于、小于等于,這里要著重說的是等于和全等于,即==和===
在JavaScript中是允許任意數據類型進行比較的
例如:
flase == 0 // true flase === 0 // false
要特別注意的是,JavaScript在設計時,有兩種比較運算符:
第一種是==比較,它會自動轉換數據類型再比較,很多時候,會得到非常詭異的結果;
第二種是===比較,它不會自動轉換數據類型,如果數據類型不一致,返回false,如果一致,再比較。
在JavaScript中推薦任何時候都是用===,而不去使用==
浮點數的相等的比較
1 / 3 === (1 - 2 / 3) // false
可能會有人有疑問,為什么1/3和1 - 2/3的值不相等,原因是:浮點數在運算過程中會產生誤差,因為計算機無法精確表示無限循環小數。
所以,要比較兩個浮點數是否相等,只能計算它們之差的絕對值,看是否小于某個閾值:
Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001 // true
一個特例:NAN
NaN這個特殊的Number與所有其他值都不相等,包括它自己:
NaN === NaN // false
唯一能判斷NAN的方法是使用isNaN()函數
isNaN(NaN) // true主角們 字符串String
字符串是以單引號""或雙引號""括起來的任意文本,比如"abc","xyz"等等。請注意,""或""本身只是一種表示方式,并不是字符串的一部分。
單引號和雙引號的功能在js中和PHP的功能并不一致,在PHP中雙引號里面可以解析變量,單引號不可以,但是在js中,單引號和雙引號并無任何區別,都不能解析變量。
所以,現在前端圈更推薦字符串只使用""單引號。
拼接字符串
和PHP不同的是js的拼接字符串使用的是+
let firstName = "蘇" let lastName = "秦" let username = firstName + lastName console.log(username) // 蘇秦
當多個變量需要連接時,使用+就比較麻煩了,例如:
var name = "劉德華" var time = "2017.12.30" var addr = "上海東方體育中心" var message = time + "國際巨星" + name + "將在" + addr + "開個人演唱會!" cosnole.log(message) // 2017.12.30國際巨星劉德華將在上海東方體育中心開個人演唱會!
模板字符串(ES6的語法糖)
為了解決多個字符串變量拼接麻煩的問題,ES6新增了一種模板字符串,是用反引號`,將變量使用${}`包裹,上面的例子使用末班字符串就可以這樣寫:
var name = "劉德華" var time = "2017.12.30" var addr = "上海東方體育中心" var message = `${time}國際巨星${name}將在${addr}開個人演唱會` cosnole.log(message) // 2017.12.30國際巨星劉德華將在上海東方體育中心開個人演唱會!
在ES6中反引號還有一個好用的點,是多行字符串
正常我們想拼接多行字符串,往往是在后面加上 ,在ES6中我們可以直接在反引號里面換行,例如:
var str = `這是 一個 多行 字符串` console.log(str)
操作字符串(js內置的一些字符串的操作函數和屬性)
獲取字符串長度(length)
length // 這個是屬性,其他的是方法
var str = "sfjhhgsd" str.length // 獲取字符串長度 8
獲取某個位置的字符串,使用字符串的索引
字符串的的索引是從0開始
var str = "hello world" str[0] // h str[4] // o str[6] // w
需要特別注意的是,字符串是不可變的,如果對字符串的某個索引賦值,不會有任何錯誤,但是,也沒有任何效果:
var s = "Test"; s[0] = "X"; console.log(s); // s仍然為"Test"
字符串大小寫轉換
toUpperCase() 把一個字符串全部轉換成大寫,生成的是一個新字符串,原字符串并不會被修改
var str = "shdkhjfkj" str.toUpperCase() // SHDKHJFKJ console.log(str) // shdkhjfkj
toLowerCase() 把一個字符串全部轉換為小寫,同樣的也是不會去修改元字符串,會生成一個新的字符串
var str = "SDGSGDHD" str.toLowerCase() // sdgsgdhd
搜索某個字符串出現的位置
indexOf() 會搜索指定字符串第一次出現的位置,當要搜索的字符串不存在該字符串時會返回-1
var str = "hsfhshlkjhkg" str.indexOf("a") // 不存在a,返回 -1 str.indexOf("s") // 第一次出現的索引位置是 1 ,第一個字符串索引為0
截取指定區間的字符串
substring() 返回指定索引區間的子串,不會修改原字符串
var str = "hello world" str.substring(1,4) // 從索引1開始到4(不包括4),返回 "ell" str.substring(7) // 從索引7開始到結束,返回"world"
將指定符號分隔的字符串轉成數組,類似PHP中的explode()
split() 方法用于把一個字符串分割成字符串數組
var str = "saboran,18,shanhai,phper" str.split(",") // 將使用英文逗號分隔的字符串轉成數組 ["saboran", "18", "shanhai", "phper"]數組Array
簡介
JavaScript的Array可以包含任意數據類型,并通過索引來訪問每個元素。
一個重要的的點是:js里的數組只有索引數組,并沒有PHP語言里的關聯數組,就是說js的數組的鍵值的鍵只能是數字,不能是字符串。
操作數組
length
要取得Array的長度,直接訪問length屬性
var arr = [1,2,"tt",null,true] arr.length // 5
注意1:直接給Array的length賦一個新的值會導致Array大小的變化
var arr = [1,2,3] arr.length // 3 arr.length = 6 // 將數組長度設置為6 arr // arr變為 [1, 2, 3, empty × 3] arr.length = 2 // 將數組長度設置為2 arr // arr變為[1,2]
Array可以通過索引把對應的元素修改為新的值,因此,對Array的索引進行賦值會直接修改這個Array
var arr = ["A", "B", "C"] arr[1] = 99 arr // arr現在變為["A", 99, "C"]
注意2:如果通過索引賦值時,索引超過了范圍,同樣會引起Array大小的變化
var arr = [1, 2, 3]; arr[5] = "x"; arr; // arr變為[1, 2, 3, undefined, undefined, "x"]
大多數其他編程語言不允許直接改變數組的大小,越界訪問索引會報錯。然而,JavaScript的Array卻不會有任何錯誤。在編寫代碼時,不建議直接修改Array的大小,訪問索引時要確保索引不會越界。
indexOf()
與String類似,Array也可以通過indexOf()來搜索一個指定的元素的位置
var arr = [10, 20, "30", "xyz"]; arr.indexOf(10); // 元素10的索引為0 arr.indexOf(20); // 元素20的索引為1 arr.indexOf(30); // 元素30沒有找到,返回-1 arr.indexOf("30"); // 元素"30"的索引為2
slice()
slice()就是對應String的substring()版本,它截取Array的部分元素,然后返回一個新的Array,slice()的起止參數包括開始索引,不包括結束索引
var arr = ["A", "B", "C", "D", "E", "F", "G"]; arr.slice(0, 3); // 從索引0開始,到索引3結束,但不包括索引3: ["A", "B", "C"] arr.slice(3); // 從索引3開始到結束: ["D", "E", "F", "G"]
如果不給slice()傳遞任何參數,它就會從頭到尾截取所有元素。利用這一點,我們可以很容易地復制一個Array
var arr = ["A", "B", "C", "D", "E", "F", "G"]; var aCopy = arr.slice(); aCopy; // ["A", "B", "C", "D", "E", "F", "G"] aCopy === arr; // false
push()和pop()
push()向Array的末尾添加若干元素,pop()則把Array的最后一個元素刪除掉
var arr = [1, 2]; arr.push("A", "B"); // 返回Array新的長度: 4 arr; // [1, 2, "A", "B"] arr.pop(); // pop()返回"B" arr; // [1, 2, "A"] arr.pop(); arr.pop(); arr.pop(); // 連續pop 3次 arr; // [] arr.pop(); // 空數組繼續pop不會報錯,而是返回undefined arr; // []
unshift()和shift()
如果要往Array的頭部添加若干元素,使用unshift()方法,shift()方法則把Array的第一個元素刪掉
var arr = [1, 2]; arr.unshift("A", "B"); // 返回Array新的長度: 4 arr; // ["A", "B", 1, 2] arr.shift(); // "A" arr; // ["B", 1, 2] arr.shift(); arr.shift(); arr.shift(); // 連續shift 3次 arr; // [] arr.shift(); // 空數組繼續shift不會報錯,而是返回undefined arr; // []
sort()
sort()可以對當前Array進行排序,它會直接修改當前Array的元素位置,直接調用時,按照默認順序排序
var arr = ["B", "C", "A"]; arr.sort(); arr; // ["A", "B", "C"]
reverse()
reverse()把整個Array的元素給掉個個,也就是反轉
var arr = ["one", "two", "three"]; arr.reverse(); arr; // ["three", "two", "one"]
concat()
concat()方法把當前的Array和另一個Array連接起來,并返回一個新的Array
var arr = ["A", "B", "C"]; var added = arr.concat([1, 2, 3]); added; // ["A", "B", "C", 1, 2, 3] arr; // ["A", "B", "C"]
注意:請注意,concat()方法并沒有修改當前Array,而是返回了一個新的Array
join() // 這個類似PHP的implode()
join()方法是一個非常實用的方法,它把當前Array的每個元素都用指定的字符串連接起來,然后返回連接后的字符串,類似PHP中的implode()
var arr = ["A", "B", "C", 1, 2, 3]; arr.join("-"); // "A-B-C-1-2-3"
splice() // 這個有點復雜有點繞,可以不講
splice()方法是修改Array的“萬能方法”,它可以從指定的索引開始刪除若干元素,然后再從該位置添加若干元素
var arr = ["Microsoft", "Apple", "Yahoo", "AOL", "Excite", "Oracle"]; // 從索引2開始刪除3個元素,然后再添加兩個元素: arr.splice(2, 3, "Google", "Facebook"); // 返回刪除的元素 ["Yahoo", "AOL", "Excite"] arr; // ["Microsoft", "Apple", "Google", "Facebook", "Oracle"] // 只刪除,不添加: arr.splice(2, 2); // ["Google", "Facebook"] arr; // ["Microsoft", "Apple", "Oracle"] // 只添加,不刪除: arr.splice(2, 0, "Google", "Facebook"); // 返回[],因為沒有刪除任何元素 arr; // ["Microsoft", "Apple", "Google", "Facebook", "Oracle"]
為js數組添加自己的方法
Array.prototype屬性表示 Array 構造函數的原型,并允許我們向所有Array對象添加新的屬性和方法。
例如:
/* * 如JavaScript數組本身不提供 first() 方法, * 我們可以添加一個返回數組的第一個元素的新方法 */ if(!Array.prototype.first) { Array.prototype.first = function() { return this[0]; } }
在實際項目中經常用到通過數組的索引刪除數組的元素就可以給數組增加一個方法:
Array.prototype.removeByIndex = function (index) { if (index > -1) { // 通過splice去除傳入的索引及對應的值 this.splice(index, 1) } } // 調用 var arr = ["red","pink","blue"] arr.removeByIndex(1) // 執行之后的arr的值就等于["red","blue"]
數組的遍歷
for循環
var arr = ["蘋果","橘子","香蕉"] for (var i = 0; i < arr.length; i++) { console.log(i) console.log(arr[i]) }
for...in
var arr = ["滿天星","卡羅拉","薰衣草"] for (index in arr){ console.log(index) console.log(arr[index]) }
forEach
var arr = ["普羅旺斯","阿姆斯特丹","保加利亞"] arr.forEach(function(item,index){ console.log(index) console.log(item) })
for...of
var arr = ["淮北","徐州","上海"] for(var item of arr){ console.log(item) }對象
在JS中的對象就是一個以鍵值對形式存儲屬性的一個集合,每一個屬性有一個特定的名稱,并與名稱相對應的值。其實這種關系是有一個專有名稱的,我們可以稱之為映射,當然對于對象來說,除了可以通過這種方式來保持自有屬性,還可以通過繼承的方式來獲取繼承屬性。這種方式我們稱作“原型式繼承”。
對象的創建
通過new 關鍵字
當我們使用的new創建新的對象的時候,js解析器會分配一塊內存空間,用以存放當前的對象的自有屬性。之后解析器會給這一對象一個_proto_屬性指向的原型對象內容。
var obj = new Object()
通過對象直接量聲明
對象直接量就是直接通過花括號包裹的鍵值對的形式來定義當前對象的。每兩個值之間的通過逗號來進行分割。鍵和值之間通過冒號來分割。放解析器讀取到當前的內容的時候會自動的生成一個對象的內容并把當前的對象存儲在當前上下文中。
var obj = {}
對象屬性及操作
訪問屬性
訪問屬性是通過.操作符完成的,但這要求屬性名必須是一個有效的變量名。如果屬性名包含特殊字符,就必須用""括起來.
// 定義小明這個對象 var xiaoming = { name: "小明", birth: 1990, "middle-school": "No.1 Middle School", // 因為middle-school 有中劃線,所以鍵值都需要引號 height: 1.70, weight: 65, score: null } // 訪問屬性 xiaoming.name // "小明" // 因為`middle-school`不是有效的變量,在聲明變量時需要使用`""`包住,訪問屬性時也不可以使用`.`操作符,必須用`["xxx"]`來訪問 xiaoming["middle-school"] // No.1 Middle School
所以js對象屬性的訪問方式有兩種,一種是使用.操作符,一種是使用類似PHP關聯數組的訪問方式,通過鍵名訪問abj.[xxx]
當訪問一個不存在的屬性不會報錯,而是返回undefined
屬性賦值
由于JavaScript的對象是動態類型,你可以自由地給一個對象添加或刪除屬性
var xiaoming = {} xiaoming.name = "小明" xiaoming.age = 18
刪除屬性
刪除js對象的屬性使用的是delete,返回布爾值
var xiaoming = { name: "小明", age: 18 } delete xiaoming.name // 刪除小明的name屬性
注意:刪除一個對象中不存在的屬性的時候并不會報錯
JavaScript對瀏覽器對象的獲取和操作window
window對象不但充當全局作用域,而且表示瀏覽器窗口。
window對象有innerWidth和innerHeight屬性,可以獲取瀏覽器窗口的內部寬度和高度。內部寬高是指除去菜單欄、工具欄、邊框等占位元素后,用于顯示網頁的凈寬高。
對應的,還有一個outerWidth和outerHeight屬性,可以獲取瀏覽器窗口的整個寬高。
navigator
navigator.appName:瀏覽器名稱; navigator.appVersion:瀏覽器版本; navigator.language:瀏覽器設置的語言; navigator.platform:操作系統類型; navigator.userAgent:瀏覽器設定的User-Agent字符串
screen
screen對象表示屏幕的信息,常用的屬性有
screen.width:屏幕寬度,以像素為單位; screen.height:屏幕高度,以像素為單位; screen.colorDepth:返回顏色位數,如8、16、24。
location // 比較重要
location對象表示當前頁面的URL信息。例如,一個完整的URL可以用location.href獲取
location.href
location常用的方法
location.href
當不給值時,location.href獲取的是當前url信息,當給location.href一個值,例如:
location.
將會跳轉到這個地址的頁面
location.reload()
刷新當前頁面
location.assign(path)
加載一個新頁面,path為頁面地址
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/92047.html
摘要:昨天總結了一些作用域的知識前端工程師手冊之作用域,但是發表完發現忘記了一些東西,今天拾個遺。循環完畢之后,,且此時生成了個匿名函數,由于這個匿名函數處在同一個詞法作用域中,所以他們引用同一個,所以當他們執行時,自然而然就會打出。 昨天總結了一些作用域的知識【前端工程師手冊】JavaScript之作用域,但是發表完發現忘記了一些東西,今天拾個遺。昨天說到了JavaScript中沒有塊級作...
摘要:最近開始看源碼,并將源碼解讀放在了我的計劃中。將轉為數組同時去掉第一個元素之后便可以調用方法總結數組的擴展方法就解讀到這里了,相關源碼可以參考這部分。放個預告,下一篇會暫緩下,講下相關的東西,敬請期待。 Why underscore 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。 閱讀一些著名框架類庫的源碼,就好...
摘要:之前總結了的一些常見綁定情況前端工程師手冊之的筆記,但是還有一些沒有說到,今天繼續學習一下。參考資料箭頭函數你不知道的上卷 之前總結了this的一些常見綁定情況(【前端工程師手冊】JavaScript之this的筆記),但是還有一些沒有說到,今天繼續學習一下。 es6箭頭函數 先說結論:箭頭函數沒有自己的this,它是根據外層(函數或者全局,后面會說到箭頭函數作為某個對象的方法時的情況...
閱讀 1426·2021-10-11 11:12
閱讀 3256·2021-09-30 09:46
閱讀 1639·2021-07-28 00:14
閱讀 3143·2019-08-30 13:49
閱讀 2591·2019-08-29 11:27
閱讀 3245·2019-08-26 11:52
閱讀 609·2019-08-23 18:14
閱讀 3444·2019-08-23 16:27