javascript
菜鸟教程 之 JavaScript 教程
From:菜鳥教程?JavaScript:https://www.runoob.com/
W3School?JavaScript 教程:http://www.w3school.com.cn/js/index.asp? ??https://www.w3cschool.cn/javascript/
廖雪峰官網 JavaScript 教程:https://www.liaoxuefeng.com/wiki/1022910821149312
MDN?JavaScript:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
知乎 JavaScript :https://www.zhihu.com/search?type=content&q=javascript
Node.js 教程:http://www.runoob.com/nodejs/nodejs-tutorial.html
400多個JavaScript特效大全:https://www.cnblogs.com/xiaoyunxiao/archive/2012/04/04/2431583.html
?
?
前言
?
- JavaScript 是 Web 的編程語言,也是一種輕量級的編程語言。所有現代的 HTML 頁面都使用 JavaScript。
- JavaScript 可以嵌入到 HTML 頁面。在 HTML 頁面中插入 JavaScript 時使用 <script> 標簽。<script> 和 </script> 會告訴 JavaScript 在何處開始和結束。<script> 和 </script> 之間的代碼行包含了 JavaScript 代碼。
- JavaScript 插入 HTML 頁面后,可以在 HTML 頁面的任何地方調用 JS 函數 (必須用英文雙引號 "js函數" 或者單引號 'j函數' 包括),然后由所有的現代瀏覽器執行。JavaScript 語句是發給瀏覽器的命令。這些命令的作用是告訴瀏覽器要做的事情。
? ? ? ? HTML事件是發生在 HTML 元素上的事情。當在 HTML 頁面中使用 JavaScript 時, JavaScript 可以觸發這些事件。
? ? ? ? HTML 事件可以是瀏覽器行為,也可以是用戶行為。
? ? ? ? HTML 事件的部分實例:HTML 頁面完成加載、HTML input 字段改變時、HTML 按鈕被點擊 等。
? ? ? ? 通常,當事件發生時,你可以做些事情。即事件觸發時 JavaScript 可以執行一些代碼。HTML 元素中可以添加事件屬性。
? ? ? ? 單引號:<some-HTML-element?some-event='JavaScript 代碼'>
? ? ? ? 雙引號:<some-HTML-element?some-event="JavaScript 代碼">
- 經常看到?document.getElementById("some id")。這個方法是 HTML DOM 中定義的。DOM (Document?Object?Model)(文檔對象模型)是用于訪問 HTML 元素的正式 W3C 標準。
- HTML 中的 js 腳本必須位于 <script> 與 </script> 標簽之間。但是 js 腳本的調用可以在HTML 頁面的任何部分。
- JavaScript 對大小寫敏感。函數?getElementById?與?getElementbyID?是不同的。同樣,變量?myVariable?與?MyVariable?也是不同的。
?
示例:
<html> <head><script>function myfunction(){document.getElementById("demo").innerHTML = "onclick事件觸發";}</script> </head> <body><h1 id="demo">一個段落</h1><button onClick="myfunction()" type="button">點擊這里</button> </body> </html> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body><h1>我的第一個 Web 頁面</h1> <p>我的第一個段落。</p> <button onclick="myFunction()">點我_1</button> <button onclick="window.alert('test');">點我_2</button> <script>function myFunction(){document.write(Date());} </script></body> </html>HTML 輸出流中使用 document.write,相當于添加在原有html代碼中添加一串html代碼。而如果在文檔加載后使用(如使用函數),會覆蓋整個文檔。
使用函數來執行 document.write 代碼如下:
<script> function myfunction(){document.write("使用函數來執行doucment.write,即在文檔加載后再執行這個操作,會實現文檔覆蓋"); } document.write("<h1>這是一個標題</h1>"); document.write("<p>這是一個段落。</p>"); </script> <p > 只能在 HTML 輸出流中使用 <strong>document.write</strong>。 如果在文檔已加載后使用它(比如在函數中),會覆蓋整個文檔。 </p> <button type="button" onclick="myfunction()">點擊這里</button>?
?
作用域
?
理解JavaScript中的作用域和上下文:https://www.h5w3.com/57138.html
關于詞法作用域的小疑惑:https://www.h5w3.com/62830.html
JavaScript 預編譯與作用域:https://www.h5w3.com/70576.html
深入理解js作用域:https://www.h5w3.com/34296.html
js深入理解] 作用域一系列問題:https://www.h5w3.com/32056.html
JavaScript進階-執行上下文棧和變量對象:https://juejin.cn/post/6844904033308655623
?
?
Window 對象
?
window對象:window對象表示一個瀏覽器窗口或一個框架。在客戶端JavaScript中,window對象是全局對象,所有的表達式都在當前的環境中計算。也就是說,要引用當前窗口根本不需要特殊的語法,可以把那個窗口的屬性當作全局變量來使用。例如,可以只寫document,而不必寫window.document。
- 所有瀏覽器都支持 window 對象。它表示瀏覽器窗口。
- 所有 JavaScript 全局對象、函數以及變量均自動成為 window 對象的成員。
- 全局變量是 window 對象的屬性。
- 全局函數是 window 對象的方法。
? ? 甚至 HTML DOM 的 document 也是 window 對象的屬性之一:
? ? ? ? ? ? window.document.getElementById("header");
? ? 與此相同:
? ? ? ? ? ? document.getElementById("header");
?
JS 中的概念區分:global對象、window對象、document對象
?
1、Global Object (全局對象, global對象)
- ①JavaScript 中有一個特殊的對象,稱為全局對象(Global Object),它及其所有屬性都可以在程序的任何地方訪問,即全局變量。
- ② 全局對象是預定義的對象,作為 JavaScript 的全局函數和全局屬性的占位符。通過使用全局對象,可以訪問所有其他所有預定義的對象、函數和屬性。全局對象不是任何對象的屬性,所以它沒有名稱。
- ③ 在頂層 JavaScript 代碼中,可以用關鍵字 this 引用全局對象。但通常不必用這種方式引用全局對象,因為全局對象是作用域鏈的頭,這意味著所有非限定性的變量和函數名都會作為該對象的屬性來查詢。例如,當JavaScript 代碼引用 parseInt() 函數時,它引用的是全局對象的 parseInt 屬性。全局對象是作用域鏈的頭,還意味著在頂層 JavaScript 代碼中聲明的所有變量,都將成為全局對象的屬性。
- ④ 全局對象只是一個對象,而不是類。既沒有構造函數,也無法用new實例化一個新的全局對象。
- ⑤ 實際上,ECMAScript 標準沒有規定全局對象的類型,而在客戶端 JavaScript 中,全局對象就是 Window 對象,即運行?JavaScript 代碼的 Web 瀏覽器窗口。瀏覽器把全局對象作為 window 對象 的一部分實現了,因此,所有的全局屬性和函數都是window對象的屬性和方法。?
通俗化理解:
- 《JavaScript高級程序設計》中談到,global 對象可以說是 ECMAScript 中最特別的一個對象了,因為不管你從什么角度上看,這個對象都是不存在的。從某種意義上講,它是一個終極的“兜底兒對象”,換句話說呢,就是不屬于任何其他對象的屬性和方法,最終都是它的屬性和方法。我理解為,這個global對象呢,就是整個JS的“老祖宗”,找不到歸屬的那些“子子孫孫”都可以到它這里來認祖歸宗。所有在全局作用域中定義的屬性和函數,都是global對象的屬性和方法,比如isNaN()、parseInt()以及parseFloat()等,實際都是它的方法;還有就是常見的一些特殊值,如:NaN、undefined等都是它的屬性,以及一些構造函數Object、Array等也都是它的方法。總之,記住一點:global對象就是“老祖宗”,所有找不到歸屬的就都是它的。
注意:
- "global" 這個單詞本身是不可以直接訪問的,本身就是一個概念,就是中文 "全局"?的英文原義,"Global Object" 翻譯就是 "全局對象"?或 "global對象"。比如:global.Math.abs(1) 就是錯誤的,訪問全局對象的屬性時往往省略前綴,如:Math.abs(1) 就行了。而 window對象 是瀏覽器的JavaScript中具體存在的一個全局對象,是可以直接訪問的。
示例 1:?( test.html ):
<script type="text/javascript">console.log(this); </script><body><h1>console.log(this);</h1> </body>打開 chrome 瀏覽器的 控制臺,看到輸出什么了嗎?
window對象! 因為在全局作用域下,this 指向全局對象。在瀏覽器中全局對象就是 window 對象。
示例 2:
<script type="text/javascript">console.log(window); </script><body><h1>console.log(window);</h1> </body>打開 chrome 瀏覽器的控制臺:
輸出 window對象,說明 "window"這個單詞在瀏覽器JS中代表的就是一個真實存在的全局的對象,可以直接訪問window這對象的。
示例 3:
<script type="text/javascript">console.log(global); </script><body><h1>console.log(global);</h1> </body>運行結果:
顯示 "Uncaught ReferenceError:global is not defined"。即global未定義,說明"global"這個單詞不是一個默認的全局對象,不能在JS中直接訪問的。正如前面所說,“global”只是中文”全局“的英語原義,不是一個對象,而是一個概念。
global 的屬性和方法:http://blog.csdn.net/qq_32758013/article/details/74781788
?
2、window 對象
在全局作用域中聲明的變量、函數都是window對象的屬性和方法。
window對象 是相對于web瀏覽器而言的,依賴于瀏覽器,在瀏覽器中全局對象指的就是window對象,可以說window對象是全局對象在瀏覽器中的具體表現。
window 并不是ECMAScript規定的內置對象。內置對象的定義是:“由ECMAScript實現提供的、不依賴于宿主環境的對象,這些對象在ECMAScript程序執行之前就已經存在了。”? 而 window對象就是宿主對象。而全局對象是在任何環境中都存在的。window對象具體也就是指瀏覽器打開的那個窗口。如果HTML文檔包含框架(frame 或 iframe 標簽),瀏覽器會為 HTML 文檔創建一個 window 對象,并為每個框架創建一個額外的 window 對象。
因此,在全局作用域中聲明的所有變量和函數,就都成為了window對象的屬性。
來看下面的例子:
<script type="text/javascript">var name = "chunlynn";var color = "green"function sayName(){console.log(name);}function sayColor(){console.log(window.color);}sayName(); // output:chunlynnwindow.sayName(); // output:chunlynnsayColor(); // output:greenwindow.sayColor(); //output:green </script><body><h1>"Test"</h1> </body>打開 chrome 瀏覽器的控制臺:
這里定義了一個名為color 的全局變量和一個名為sayColor()的全局函數。在sayColor()內部,我們通過window.color 來訪問color 變量,說明全局變量是window 對象的屬性。然后又使用window.sayColor()來直接通過window 對象調用這個函數,說明全局作用域中聲明的函數是window對象的方法。window對象一般是省略的。
window 對象的屬性和方法:http://www.cnblogs.com/zengwei/archive/2007/11/02/946520.html
window的屬性和方法比較多,這個鏈接可能說的不全僅供參考,具體的請在 chrome 后臺中,輸入window查看
?
3、document對象
document對象是window對象的一個屬性,是顯示于窗口內的一個文檔。而 window 對象則是一個頂層對象,它不是另一個對象的屬性。
document 可以理解為文檔,就是你的網頁,而 window 是你的窗口,就是你的瀏覽器包含的。
區別:
- ① window 指窗體。document指頁面。document是window的一個屬性。?
- ② 用戶不能改變 document.location(因為這是當前顯示文檔的位置)。但是,可以改變window.location (用其它文檔取代當前文檔)window.location本身也是一個對象,而document.location不是對象
- ③ W3C官方說明文檔
? ? Window對象:http://www.w3school.com.cn/htmldom/dom_obj_window.asp
? ? Document對象:http://www.w3school.com.cn/htmldom/dom_obj_document.asp
?
?
在各種 JavaScript 運行環境中取得全局對象 global 的方法
From:https://www.cnblogs.com/emmet7life/p/7691681.html
ES5 的頂層對象,本身也是一個問題,因為它在各種實現里面是不統一的。
- 瀏覽器里面,頂層對象是window,但 Node 和 Web Worker 沒有window。
- 瀏覽器和 Web Worker 里面,self也指向頂層對象,但是 Node 沒有self。
- Node 里面,頂層對象是global,但其他環境都不支持。
同一段代碼為了能夠在各種環境,都能取到頂層對象,現在一般是使用this變量,但是有局限性。
- 全局環境中,this會返回頂層對象。但是,Node 模塊和 ES6 模塊中,this返回的是當前模塊。
- 函數里面的this,如果函數不是作為對象的方法運行,而是單純作為函數運行,this會指向頂層對象。但是,嚴格模式下,這時this會返回undefined。
- 不管是嚴格模式,還是普通模式,new Function('return this')(),總是會返回全局對象。但是,如果瀏覽器用了CSP(Content Security Policy,內容安全政策),那么eval、new Function這些方法都可能無法使用。
綜上所述,很難找到一種方法,可以在所有情況下,都取到頂層對象。下面是兩種勉強可以使用的方法。
// 方法一 (typeof window !== 'undefined'? window: (typeof process === 'object' &&typeof require === 'function' &&typeof global === 'object')? global: this);// 方法二 var getGlobal = function () {if (typeof self !== 'undefined') { return self; }if (typeof window !== 'undefined') { return window; }if (typeof global !== 'undefined') { return global; }throw new Error('unable to locate global object'); };現在有一個提案,在語言標準的層面,引入global作為頂層對象。也就是說,在所有環境下,global都是存在的,都可以從它拿到頂層對象。
墊片庫system.global模擬了這個提案,可以在所有環境拿到global。
// CommonJS 的寫法 require('system.global/shim')();// ES6 模塊的寫法 import shim from 'system.global/shim'; shim();上面代碼可以保證各種環境里面,global對象都是存在的。
// CommonJS 的寫法 var global = require('system.global')();// ES6 模塊的寫法 import getGlobal from 'system.global'; const global = getGlobal();上面代碼將頂層對象放入變量?global。
?
?
this 對象 詳解參考
?
this 永遠指向 最后調用它 的 那個對象。。。?
但是 箭頭函數 的 this 是由 外層作用域決定的
【1】JS/JavaScript中 this 關鍵字對象詳解:http://blog.csdn.net/chenchunlin526/article/details/78889301
?
this 概述
this 是面向對象語言中的一個重要概念,在 JAVA,C# 等大型語言中,this 固定指向運行時的當前對象。但是在 JavaScript中,由于 JavaScript 的動態性(解釋執行,當然也有簡單的預編譯過程),this 的指向在運行時才確定。這個特性在給我們帶來迷惑的同時,也帶來了編程上的自由和靈活,結合 apply、call、bind 方法,可以使 JS 變得異常強大。this 是 Javascript 語言的一個關鍵字,它代表函數運行時自動生成的一個內部對象,一般在函數內部使用。
- ① this 的值通常是由所在函數的執行環境決定,也就是說要看函數是如何被調用的;
- ② 同一個函數每一次調用,this 都可能指向不同的對象;
先看下面一段簡單的代碼:
<script type="text/javascript">var name = "javascript";var obj = {name:'chunlynn',foo: function(){console.log(this.name);}}obj.foo(); //output:chunlynnconsole.log(this.name) </script>問題1:obj是JavaScript中的什么類型?(想一想再往下看)
- 答案為:obj是js中的對象類型(Object類型)。對象就是一些屬性和方法的集合。
問題2:如果執行obj.foo(),會在控制臺輸出什么呢?
- 答案為:chunlynn。
通過上面的這個小例子簡單的認識下this:this 是 JS 對象中的一個特殊指針,它的指向根據環境不同而會發生改變。
?
?
面向對象語言中 this 表示當前對象的一個引用。
但在 JavaScript 中 this 不是固定不變的,它會隨著執行環境的改變而改變。
- 在方法中,this 表示該方法所屬的對象。
- 如果單獨使用,this 表示全局對象。
- 在函數中,this 表示全局對象。
- 在函數中,在嚴格模式下,this 是未定義的(undefined)。
- 在事件中,this 表示接收事件的元素。
- 類似 call() 和 apply() 方法可以將 this 引用到任何對象。
示例:
var person = {firstName: "John",lastName : "Doe",id : 5566,fullName : function() {return this.firstName + " " + this.lastName;} };console.log(person.fullName());?
- 方法中的 this。在對象方法中, this 指向調用它所在方法的對象。上面實例中,this 表示 person 對象。fullName 方法所屬的對象就是 person。
- 單獨使用 this。單獨使用 this 時則它指向?全局(Global)對象。在瀏覽器中,window 就是該全局對象為 [object Window]:
示例:var x = this;? 嚴格模式下,如果單獨使用,this 也是指向全局(Global)對象。示例:"use strict";? var x = this;
- 事件中的 this。在 HTML 事件句柄中,this 指向了接收事件的 HTML 元素: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body><h2>JavaScript <b>this</b> 關鍵字</h2><button onclick="this.style.display='none'">點我后我就消失了</button></body> </html>
-
對象方法中綁定。下面實例中,this 是 person 對象,person 對象是函數的所有者。示例:
var person = {firstName : "John",lastName : "Doe",id : 5566,myFunction : function() {return this;} };示例:(?說明:?this.firstName?表示?this?(person) 對象的?firstName?屬性。 )
var person = {firstName: "John",lastName : "Doe",id : 5566,fullName : function() {return this.firstName + " " + this.lastName;} }; -
顯式函數綁定。在 JavaScript 中函數也是對象,對象則有方法,apply 和 call 就是函數對象的方法。這兩個方法異常強大,他們允許切換函數執行的上下文環境(context),即 this 綁定的對象。在下面實例中,當我們使用 person2 作為參數來調用 person1.fullName 方法時,?this?將指向 person2, 即便它是 person1 的方法:
var person1 = {fullName: function() {return this.firstName + " " + this.lastName;} } var person2 = {firstName:"John",lastName: "Doe", } person1.fullName.call(person2); // 返回 "John Doe"?
?
this 指向 的?用法分類詳解
?
1、對象構造函數中的this (new關鍵字構造對象)
當使用new關鍵字構建一個新的對象,this會綁定到這個新對象。
<script type="text/javascript">var name = "chunlynn";//構造函數function Foo(){this.name = 'linda';this.foo = function(){console.log(this.name);}}var obj = new Foo(); // 實例化對象obj.foo(); //output:linda </script>注意構造函數和普通函數的區別,構造的屬性用 this.name="chunlynn",普通函數用 var name = 'linda'。構造函數函數名稱大寫。
?
2、 普通函數中的this
?作為普通函數直接調用時,this 指向 window對象.?
<script type="text/javascript">var name = "chunlynn";//普通函數function foo(){var name = 'linda';console.log(this.name);}foo(); //output:chunlynn </script>下面再來看一個有些難度的:
<script type="text/javascript">var name = "chunlynn";//構造函數function Foo (){this.name = 'linda';this.foo = function(){var name = 'doudou';return function(){console.log(this.name);};}}var obj = new Foo(); // 實例化對象obj.foo()(); //output:chunlynn// 拆開分步執行如下:// var re = obj.foo();// re(); ---> window.re();// 這里是window調用的foo()函數,所以this指向window對象, this.name指的就是chunlynn </script>?
3、onclick(this)中的this指向
對于一個onclick屬性,它為它所屬的HTML元素所擁有,this指向該HTML元素。
<a href="javascript:void(0);" title="這個是一個標題!!" onclick="test(this);">A標簽測試</a> <script type="text/javascript">function test(obj){var value = obj.title;console.log(value); //這是一個標題!!} </script>onclick 為它所屬的 <a> 元素所有,this 指向 <a> 元素。
?
4、定時器 setTimeout 中的 this 指向
定時器中的this指向window對象。因為定時器就是全局函數,由window調用。
先來看一個定時器的例子:
<script type="text/javascript">var name = "chunlynn";//普通函數function foo(){var name = 'linda';console.log(this.name);}setTimeout(foo, 5000); //output:chunlynn// this指向:誰調用或者哪個對象調用this所在的函數,this就指向誰。// 定時器為全局函數,由window調用,因此定時器中的this指向window對象。 </script>下題輸出結果是多少,說明為什么。
<script type="text/javascript">var name = "chunlynn";var obj = {name:'linda',fn: function(){console.log(this.name);},foo:function(){setTimeout(this.fn, 5000);}}obj.foo(); //output:chunlynn// this指向:誰調用或者哪個對象調用this所在的函數,this就指向誰。// 嵌套帶入進去最終執行的就是// window.setTimeout(function (){console.log(this.name)}, 5000); this指向的就是window對象 </script>換個思路,上面最終執行的代碼為:
<script type="text/javascript">window.setTimeout(function (){// this指向的就是window對象,直接包含this.name的為setTimeout函數console.log(this.name);}, 5000); </script>這樣答案一目了然了吧,this 綁定到了 window 對象。
?
5、使用 apply、call 或 bind 方法時 this 的指向
使用apply 、call 或 bind方法時,this指向所傳遞的對象。?
<script type="text/javascript">var name = "chunlynn";var obj = {name:'linda',foo:function(){console.log(this.name);}}var f = {};f.name = "doudou";f.fun = obj.foo; //將obj對象的foo函數賦值給f對象的fun屬性。本質為復制。f.fun(); //output:doudouf.fun.apply(obj); //output:lindaf.fun.apply(window); //output:doudouf.fun.apply(); //output:chunlynn// this指向:誰調用或者哪個對象調用this所在的函數,this就指向誰。 </script>apply() 的參數為空時,默認調用全局對象 window。
查看 chrome 瀏覽器控制臺:
?
6、ES6 箭頭函數 和 this
箭頭函數的特征就是:定義在哪,this 就指向那。
//es6中的雙箭頭操作符,類似于java中的lamada表達式 <script type="text/javascript">var author = "chunlynn";var book = {name: 'linda',init: function(){setTimeout(ev=>{console.log(this.name);},3000);}}book.init(); //output:linda// this指向:誰調用或者哪個對象調用this所在的函數,this就指向誰。 </script>箭頭函數的特征就是:定義在哪,this 就指向那。即箭頭函數定義在一個對象里,那箭頭函數里的 this 就指向該對象。
?
總結
- ① 誰調用 或者 哪個對象調用 this 所在的函數,this 就指向誰。 如果有嵌套調用,則其值會被綁定到調用 this 所在函數的最近的父對象 ,不論這個 this 出現在什么樣的函數中,層次有多深,結構多復雜,只要看直接包含它的函數即可。
- ② “this” always refers to the “owner” of the function we're executing。
- ③?this 通常指向的是我們正在執行的函數本身,或者是,指向該函數所屬的對象。
- ④?this 是 Javascript 語言的一個關鍵字,它代表函數運行時自動生成的一個內部對象,只能在函數內部使用。
?
?
JavaScript?輸出
?
JavaScript 沒有任何打印或者輸出的函數。JavaScript 可以通過不同的方式來輸出數據:
- 使用?window.alert()?彈出警告框。
- 使用?document.write()?方法將內容寫到 HTML 文檔中。
- 使用?innerHTML?寫入到 HTML 元素。
- 使用?console.log()?寫入到瀏覽器的控制臺。
?
?
JavaScript 變量
?
JavaScript 變量均為 對象。當聲明一個變量時,就創建了一個新的對象。?JavaScript? 一切皆對象。
?
聲明(創建)
在 JavaScript 中創建變量通常稱為"聲明"變量。使用 var 關鍵詞來聲明變量:var carname;
變量聲明之后,該變量是空的(它沒有值)。如需向變量賦值,請使用等號:carname="Volvo";
也可以在聲明變量時對其賦值:var carname="Volvo";
示例:創建名為 carname 的變量,并向其賦值 "Volvo",然后把它放入 id="demo" 的 HTML 段落中:
var carname="Volvo"; document.getElementById("demo").innerHTML=carname;?
一條語句,多個變量
可以在一條語句中聲明很多變量。該語句以 var 開頭,并使用逗號分隔變量即可:var lastname="Doe", age=30, job="carpenter";
聲明也可橫跨多行:
var lastname="Doe", age=30, job="carpenter";一條語句中聲明的多個變量不可以同時賦同一個值:
var x,y,z=1; // x,y 為 undefined, z 為 1。?
Value = undefined
在計算機程序中,經常會聲明無值的變量。未使用值來聲明的變量,其值實際上是 undefined。
在執行過以下語句后,變量 carname 的值將是 undefined:var carname;
?
重新聲明 JavaScript 變量
如果重新聲明 JavaScript 變量,該變量的值不會丟失:
在以下兩條語句執行后,變量 carname 的值依然是 "Volvo":
var carname="Volvo"; var carname;?
?
變量提升
?
JavaScript 嚴格模式(strict mode)不允許使用未聲明的變量。
JavaScript 中,函數及變量的聲明都將被提升到函數的最頂部。
JavaScript 中,變量可以在使用后聲明,也就是 變量可以先使用再聲明。
示例 1:( 提升 變量y?)
var x = 10; // 初始化 x y = 20; console.log(x + "" + y); // y 是先使用,后面聲明 var y; // 聲明 變量 y console.log(x + "" + y);示例 2:
var x; // 聲明 x x = 10; // 變量 x 設置為 10console.log(x)要理解以上實例就需要理解 "hoisting(變量提升)"。
變量提升:函數聲明 和 變量聲明 總是會被解釋器悄悄地被 "提升" 到 方法體的最頂部。
JavaScript 初始化不會提升:即 JavaScript 只有聲明的變量會提升,初始化的不會。
JavaScript 只有聲明的變量會提升,初始化的不會。示例說明:
示例 1:初始化變量
var x = 5; // 初始化 x var y = 7; // 初始化 y console.log(x + y);示例 2:(??y 輸出了?undefined,這是因為變量聲明 (var y) 提升了,但是初始化(y = 7) 并不會提升,所以 y 變量是一個未定義的變量。 )
var x = 5; // 初始化 x console.log(x + "" + y); // y 是先使用,后面聲明和初始化var y = 7; // 初始化 y?
?
JavaScript 嚴格模式(use strict)
?
JavaScript 嚴格模式(strict mode)即在嚴格的條件下運行。
"use strict" 指令只允許出現在 腳本 或 函數 的開頭。
使用 "use strict" 指令
- "use strict" 指令在 JavaScript 1.8.5 (ECMAScript5) 中新增。它不是一條語句,但是是一個字面量表達式,在 JavaScript 舊版本中會被忽略。
- "use strict" 的目的是指定代碼在嚴格條件下執行。嚴格模式下你不能使用未聲明的變量。
- 嚴格模式的聲明:嚴格模式通過在腳本或函數的頭部添加?use strict; 表達式來聲明。
示例代碼:
"use strict"; x = 3.14; // 報錯 (x 未定義) "use strict"; myFunction();function myFunction() {y = 3.14; // 報錯 (y 未定義) }在函數內部聲明是局部作用域 (只在函數內使用嚴格模式)。示例:
x = 3.14; // 不報錯 myFunction();function myFunction() {"use strict";y = 3.14; // 報錯 (y 未定義) }為什么使用嚴格模式:
- 消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為;
- 消除代碼運行的一些不安全之處,保證代碼運行的安全;
- 提高編譯器效率,增加運行速度;
- 為未來新版本的Javascript做好鋪墊。
"嚴格模式"體現了Javascript更合理、更安全、更嚴謹的發展方向,包括IE 10在內的主流瀏覽器,都已經支持它,許多大項目已經開始全面擁抱它。
另一方面,同樣的代碼,在"嚴格模式"中,可能會有不一樣的運行結果;一些在"正常模式"下可以運行的語句,在"嚴格模式"下將不能運行。掌握這些內容,有助于更細致深入地理解Javascript,讓你變成一個更好的程序員。
?
嚴格模式的限制
1. 不允許使用未聲明的變量。
"use strict"; x = 3.14; // 報錯 (x 未定義)對象也是一個變量
"use strict"; x = {p1:10, p2:20}; // 報錯 (x 未定義)2.?不允許刪除變量或對象。
"use strict"; var x = 3.14; delete x; // 報錯3.?不允許刪除函數。
"use strict"; function x(p1, p2) {}; delete x; // 報錯4.?不允許變量重名:
"use strict"; function x(p1, p1) {}; // 報錯5.?不允許使用八進制:
"use strict"; var x = 010; // 報錯6.?不允許使用轉義字符:
"use strict"; var x = \010; // 報錯7.?不允許對只讀屬性賦值:
"use strict"; var obj = {}; Object.defineProperty(obj, "x", {value:0, writable:false});obj.x = 3.14; // 報錯8.?不允許對一個使用 getter 方法讀取的屬性進行賦值
"use strict"; var obj = {get x() {return 0} };obj.x = 3.14; // 報錯9.?不允許刪除一個不允許刪除的屬性:
"use strict"; delete Object.prototype; // 報錯10.?變量名不能使用 "eval" 字符串:
"use strict"; var eval = 3.14; // 報錯11.?變量名不能使用 "arguments" 字符串:
"use strict"; var arguments = 3.14; // 報錯12.?不允許使用以下這種語句:
"use strict"; with (Math){x = cos(2)}; // 報錯13.?由于一些安全原因,在作用域 eval() 創建的變量不能被調用:
"use strict"; eval ("var x = 2"); alert (x); // 報錯14.?禁止this關鍵字指向全局對象。
function f(){return !this; } // 返回false,因為"this"指向全局對象,"!this"就是falsefunction f(){ "use strict";return !this; } // 返回true,因為嚴格模式下,this的值為undefined,所以"!this"為true。因此,使用構造函數時,如果忘了加 new,this 不再指向全局對象,而是報錯。
function f(){"use strict";this.a = 1; }; f();// 報錯,this未定義15. 保留關鍵字
為了向將來Javascript的新版本過渡,嚴格模式新增了一些保留關鍵字:
- implements
- interface
- let
- package
- private
- protected
- public
- static
- yield
?
?
JavaScript?數據類型
?
值類型 和 引用類型(即對象類型)
- 值類型(基本類型):字符串(String)、數字(Number)、布爾(Boolean)、對空(Null)、未定義(Undefined)、Symbol。
- 引用數據類型:對象(Object)、數組(Array)、函數(Function)。
注:Symbol 是 ES6 引入了一種新的原始數據類型,表示獨一無二的值。
?
JavaScript 擁有動態類型
JavaScript 擁有動態類型。這意味著相同的變量可用作不同的類型,示例:
var x;?????????????? // x 為 undefined var x = 5;?????????? // 現在 x 為數字 var x = "John";????? // 現在 x 為字符串?
JavaScript 字符串
字符串是存儲字符(比如 "Bill Gates")的變量。
字符串可以是引號中的任意文本。您可以使用單引號或雙引號。實例:
var carname="Volvo XC60"; var carname='Volvo XC60';您可以在字符串中使用引號,只要不匹配包圍字符串的引號即可。實例:
var answer="It's alright"; var answer="He is called 'Johnny'"; var answer='He is called "Johnny"';?
JavaScript 數字
JavaScript 只有一種數字類型。數字可以帶小數點,也可以不帶。實例:
var x1=34.00;????? //使用小數點來寫 var x2=34;???????? //不使用小數點來寫極大或極小的數字可以通過科學(指數)計數法來書寫。實例:
var y=123e5;????? // 12300000 var z=123e-5;???? // 0.00123?
JavaScript 布爾
布爾(邏輯)只能有兩個值:true 或 false。布爾常用在條件測試中。
var x=true; var y=false;?
JavaScript 數組
下面的代碼創建名為 cars 的數組:
var cars=new Array(); cars[0]="Saab"; cars[1]="Volvo"; cars[2]="BMW";// 或者 (condensed array) var cars=new Array("Saab","Volvo","BMW");// 或者 (literal array): var cars=["Saab","Volvo","BMW"];數組下標是基于零的,所以第一個項目是 [0],第二個是 [1],以此類推。
?
JavaScript 對象
對象由花括號分隔。在括號內部,對象的屬性以名稱和值對的形式 (name : value) 來定義。屬性由逗號分隔:
var person={firstname:"John", lastname:"Doe", id:5566};上面例子中的對象 (person) 有三個屬性:firstname、lastname 以及 id。
空格和折行無關緊要。聲明可橫跨多行:
var person={firstname : "John",lastname? : "Doe",id??????? :? 5566 };對象屬性的兩種尋址方式
name=person.lastname; name=person["lastname"];對象屬性
JavaScript?對象:https://www.runoob.com/js/js-obj-intro.html
可以說 "JavaScript 中的對象是變量的容器"。(?JavaScript的對象 是 屬性 和 方法 的 容器。 )
但是,我們通常認為 "JavaScript 對象是鍵值對的容器"。鍵值對通常寫法為?name : value?(鍵與值以冒號分割)。鍵值對在 JavaScript 對象通常稱為?對象屬性。
對象鍵值對的寫法類似于:
- PHP 中的關聯數組
- Python 中的字典
- C 語言中的哈希表
- Java 中的哈希映射
- Ruby 和 Perl 中的哈希表
示例:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body><p>創建和使用對象方法。</p> <p>對象方法作為一個函數定義存儲在對象屬性中。</p> <p id="demo"></p> <script> var person = {firstName: "John",lastName : "Doe",id : 5566,fullName : function() {return this.firstName + " " + this.lastName;} }; document.getElementById("demo").innerHTML = person.fullName(); </script></body> </html>name = person.fullName();???// 加上 () 表示調用函數。
name = person.fullName;?? ? // 不加 () 表示屬性,屬性值 就是 函數體的代碼
?
Undefined 和 Null
Undefined 這個值表示變量不含有值。
可以通過將變量的值設置為 null 來清空變量。實例:
cars=null; person=null;?
聲明變量類型
當您聲明新變量時,可以使用關鍵詞 "new" 來聲明其類型:
var carname=new String; var x=????? new Number; var y=????? new Boolean; var cars=?? new Array; var person= new Object;?
?
JavaScript?中的 值傳遞,引用傳遞,共享傳遞
深入理解javascript按值傳遞與按引用傳遞:https://segmentfault.com/a/1190000012829900
基本類型 是 不可變類型,傳遞時 是 值傳遞
對象類型 是 不可變類型,傳遞時 是 引用傳遞
JavaScript?對函數形參的賦值是不可變類型,則不會影響實參的值,如果傳遞給形參是對象類型,由于對象是可變(mutable),當修改形參對象的屬性值,也會影響到實參的屬性值。
function changeStuff(num, obj1, obj2) {num = num * 10;obj1.item = "changed";obj2 = {item: "changed"}; }var num = 10; var obj1 = {item: "unchanged"}; var obj2 = {item: "unchanged"}; changeStuff(num, obj1, obj2); console.log(num); // 10 console.log(obj1.item); // changed console.log(obj2.item); // unchanged值傳遞
傳值的意思就是:傳內存拷貝。
函數內的num, obj1, obj2都將是一份新的內存,與調用函數之前定義的三個變量毫無關系。函數內無論怎么修改這三個參數,外部定義的三個變量的值始終不變
?
引用傳遞
傳引用的意思就是:傳內存指針
函數內的num, obj1, obj2都分別指向一塊內存,該內存就是調用函數之前定義的三個變量時創建的內存。函數內對這三個參數所做的任何改動,都將反映到外部定義的三個變量上。
?
ECMAScript中所有函數的參數都是按值傳遞的。
也就是說,把函數外部的值復制給函數內部的參數,就和把值從一個變量復制到另一個變量一樣。基本類型的傳遞如同基本類型的復制一樣,而引用類型值的傳遞,如同引用類型變量的復制一樣。總結
很簡單,javascript函數參數都是按值傳遞(都是棧內數據的拷貝)。基本類型傳的是值本身(因為直接把值存在棧內),引用類型傳的是對象在內存里面的地址 (因為復雜對象存在堆內,所以在棧里存對象所在的堆地址)。
?
共享傳遞
?
JS是按值傳遞還是按引用傳遞??在分析這個問題之前,我們需了解什么是按值傳遞(call by value),什么是按引用傳遞(call by reference)。在計算機科學里,這個部分叫求值策略(Evaluation Strategy)。它決定變量之間、函數調用時實參和形參之間值是如何傳遞的。
?
按值傳遞 VS. 按引用傳遞
按值傳遞(call by value)是最常用的求值策略:函數的形參是被調用時所傳實參的副本。修改形參的值并不會影響實參。
?
按引用傳遞(call by reference)時,函數的形參接收實參的隱式引用,而不再是副本。這意味著函數形參的值如果被修改,實參也會被修改。同時兩者指向相同的值。
?
按引用傳遞會使函數調用的追蹤更加困難,有時也會引起一些微妙的BUG。
?
按值傳遞由于每次都需要克隆副本,對一些復雜類型,性能較低。兩種傳值方式都有各自的問題。
?
我們先看一個C的例子來了解按值和引用傳遞的區別:?
這里我們可以看到:
a => p按值傳遞時,修改形參p的值并不影響實參a,p只是a的副本。
b => q是按引用傳遞,修改形參q的值時也影響到了實參b的值。
?
探究JS值的傳遞方式
JS的基本類型,是按值傳遞的。
var a = 1; function foo(x) {x = 2; } foo(a); console.log(a); // 仍為1, 未受x = 2賦值所影響再來看對象:
var obj = {x : 1}; function foo(o) {o.x = 3; } foo(obj); console.log(obj.x); // 3, 被修改了!說明 o 和 obj 是同一個對象,o 不是 obj 的副本。所以不是按值傳遞。 但這樣是否說明 JS 的對象是按引用傳遞的呢?我們再看下面的例子:
var obj = {x : 1}; function foo(o) {o = 100; } foo(obj); console.log(obj.x); // 仍然是1, obj并未被修改為100.如果是按引用傳遞,修改形參o的值,應該影響到實參才對。但這里修改o的值并未影響obj。 因此JS中的對象并不是按引用傳遞。那么究竟對象的值在JS中如何傳遞的呢?
?
按共享傳遞 call by sharing
準確的說,JS中的基本類型按值傳遞,對象類型按共享傳遞的(call by sharing,也叫按對象傳遞、按對象共享傳遞)。最早由Barbara Liskov. 在1974年的GLU語言中提出。該求值策略被用于Python、Java、Ruby、JS等多種語言。
該策略的重點是:調用函數傳參時,函數接受對象實參引用的副本(既不是按值傳遞的對象副本,也不是按引用傳遞的隱式引用)。 它和按引用傳遞的不同在于:在共享傳遞中對函數形參的賦值,不會影響實參的值。如下面例子中,不可以通過修改形參o的值,來修改obj的值。
var obj = {x : 1}; function foo(o) {o = 100; } foo(obj); console.log(obj.x); // 仍然是1, obj并未被修改為100.然而,雖然引用是副本,引用的對象是相同的。它們共享相同的對象,所以修改形參對象的屬性值,也會影響到實參的屬性值。
var obj = {x : 1}; function foo(o) {o.x = 3; } foo(obj); console.log(obj.x); // 3, 被修改了!對于對象類型,由于對象是可變(mutable)的,修改對象本身會影響到共享這個對象的引用和引用副本。而對于基本類型,由于它們都是不可變的(immutable),按共享傳遞與按值傳遞(call by value)沒有任何區別,所以說JS基本類型既符合按值傳遞,也符合按共享傳遞。
?
var a = 1; // 1是number類型,不可變 var b = a; b = 6;
據按共享傳遞的求值策略,a和b是兩個不同的引用(b是a的引用副本),但引用相同的值。由于這里的基本類型數字1不可變,所以這里說按值傳遞、按共享傳遞沒有任何區別。
?
基本類型的不可變(immutable)性質
基本類型是不可變的(immutable),只有對象是可變的(mutable). 例如數字值100, 布爾值true, false,修改這些值(例如把1變成3, 把true變成100)并沒有什么意義。比較容易誤解的,是JS中的string。有時我們會嘗試“改變”字符串的內容,但在JS中,任何看似對string值的”修改”操作,實際都是創建新的string值。
而對象就不一樣了,對象是可變的。
var obj = {x : 1}; obj.x = 100; var o = obj; o.x = 1; obj.x; // 1, 被修改 o = true; obj.x; // 1, 不會因o = true改變這里定義變量obj,值是object,然后設置obj.x屬性的值為100。而后定義另一個變量o,值仍然是這個object對象,此時obj和o兩個變量的值指向同一個對象(共享同一個對象的引用)。所以修改對象的內容,對obj和o都有影響。但對象并非按引用傳遞,通過o = true修改了o的值,不會影響obj。
?
?
JavaScript?類型轉換
?
Number() 轉換為數字, String() 轉換為字符串, Boolean() 轉換為布爾值。
?
JavaScript 數據類型
在 JavaScript 中有 6 種不同的數據類型:
- string
- number
- boolean
- object
- function
- symbol
3 種對象類型:
- Object
- Date
- Array
2 個不包含任何值的數據類型:
- null
- undefined
?
typeof 操作符
你可以使用?typeof?操作符來查看 JavaScript 變量的數據類型。
console.log(typeof "John") // 返回 string console.log(typeof 3.14) // 返回 number console.log(typeof NaN) // 返回 number console.log(typeof false) // 返回 boolean console.log(typeof [1,2,3,4]) // 返回 object console.log(typeof {name:'John', age:34}) // 返回 object console.log(typeof new Date()) // 返回 object console.log(typeof function () {}) // 返回 function console.log(typeof myCar) // 返回 undefined (如果 myCar 沒有聲明) console.log(typeof null) // 返回 object <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body><p> typeof 操作符返回變量、對象、函數、表達式的類型。</p> <p id="demo"></p> <script> document.getElementById("demo").innerHTML = typeof "john" + "<br>" +typeof 3.14 + "<br>" +typeof NaN + "<br>" +typeof false + "<br>" +typeof [1,2,3,4] + "<br>" +typeof {name:'john', age:34} + "<br>" +typeof new Date() + "<br>" +typeof function () {} + "<br>" +typeof myCar + "<br>" +typeof null; </script></body> </html>注意:
- NaN 的數據類型是 number
- 數組(Array)的數據類型是 object
- 日期(Date)的數據類型為 object
- null 的數據類型是 object
- 未定義變量的數據類型為 undefined
如果對象是 JavaScript Array 或 JavaScript Date ,我們就無法通過?typeof?來判斷他們的類型,因為都是 返回 object。
?
constructor 屬性
constructor?屬性返回所有 JavaScript 變量的 構造函數。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body><p> constructor 屬性返回變量或對象的構造函數。</p> <p id="demo"></p> <script> document.getElementById("demo").innerHTML = "john".constructor + "<br>" +(3.14).constructor + "<br>" +false.constructor + "<br>" +[1,2,3,4].constructor + "<br>" +{name:'john', age:34}.constructor + "<br>" +new Date().constructor + "<br>" +function () {}.constructor; </script></body> </html>運行結果:
constructor 屬性返回變量或對象的構造函數。function String() { [native code] } function Number() { [native code] } function Boolean() { [native code] } function Array() { [native code] } function Object() { [native code] } function Date() { [native code] } function Function() { [native code] }nodejs 執行結果:
console.log("John".constructor); // [Function: String] console.log((3.14).constructor); // [Function: Number] console.log(false.constructor); // [Function: Boolean] console.log([1,2,3,4].constructor); // [Function: Array] console.log({name:'John', age:34}.constructor); // [Function: Object] console.log(new Date().constructor) // [Function: Date] console.log(function () {}.constructor) // [Function: Function]可以使用 constructor 屬性來查看對象是否為數組 (包含字符串 "Array")。示例:判斷是否是 array
function isArray(myArray) {return myArray.constructor.toString().indexOf("Array") > -1; }var str = ''; console.log(isArray(str));使用 constructor 屬性來查看對象是否為日期 (包含字符串 "Date"):
function isDate(myDate) {return myDate.constructor.toString().indexOf("Date") > -1; }?
JavaScript 類型轉換
JavaScript 變量可以轉換為 新變量 或 其他數據類型:
- 通過使用 JavaScript 函數
- 通過 JavaScript 自身自動轉換
?
數字 轉換為 字符串
全局方法?String()?可以將數字轉換為字符串。該方法可用于任何類型的數字,字母,變量,表達式:
String(x) // 將變量 x 轉換為字符串并返回 String(123) // 將數字 123 轉換為字符串并返回 String(100 + 23) // 將數字表達式轉換為字符串并返回Number 方法?toString()?也是有同樣的效果。
var x = 12345; console.log(x.toString()); console.log((123).toString()); console.log((10000 + 23).toString());在?Number 方法?章節中,你可以找到更多數字轉換為字符串的方法:
| toExponential() | 把對象的值轉換為指數計數法。 |
| toFixed() | 把數字轉換為字符串,結果的小數點后有指定位數的數字。 |
| toPrecision() | 把數字格式化為指定的長度。 |
?
布爾值 轉換為 字符串
//全局方法 String() 可以將布爾值轉換為字符串。 String(false) // 返回 "false" String(true) // 返回 "true"// Boolean 方法toString()也有相同的效果。 false.toString()// 返回 "false" true.toString() // 返回 "true"?
將日期轉換為字符串
// Date() 返回字符串。 Date() // 返回 Thu Jul 17 2014 15:38:19 GMT+0200 (W. Europe Daylight Time)// 全局方法 String() 可以將日期對象轉換為字符串。 String(new Date()) // 返回 Thu Jul 17 2014 15:38:19 GMT+0200 (W. Europe Daylight Time)// Date 方法toString()也有相同的效果。 obj = new Date() obj.toString() // 返回 Thu Jul 17 2014 15:38:19 GMT+0200 (W. Europe Daylight Time)在?Date 方法?章節中,你可以查看更多關于日期轉換為字符串的函數:
| getDate() | 從 Date 對象返回一個月中的某一天 (1 ~ 31)。 |
| getDay() | 從 Date 對象返回一周中的某一天 (0 ~ 6)。 |
| getFullYear() | 從 Date 對象以四位數字返回年份。 |
| getHours() | 返回 Date 對象的小時 (0 ~ 23)。 |
| getMilliseconds() | 返回 Date 對象的毫秒(0 ~ 999)。 |
| getMinutes() | 返回 Date 對象的分鐘 (0 ~ 59)。 |
| getMonth() | 從 Date 對象返回月份 (0 ~ 11)。 |
| getSeconds() | 返回 Date 對象的秒數 (0 ~ 59)。 |
| getTime() | 返回 1970 年 1 月 1 日至今的毫秒數。 |
字符串 轉換為 數字
全局方法?Number()?可以將字符串轉換為數字。
字符串包含數字(如 "3.14") 轉換為數字 (如 3.14)。
空字符串轉換為 0。
其他的字符串會轉換為 NaN (不是個數字)。
在?Number 方法?章節中,你可以查看到更多關于字符串轉為數字的方法:
| parseFloat() | 解析一個字符串,并返回一個浮點數。 |
| parseInt() | 解析一個字符串,并返回一個整數。 |
一元運算符 +
Operator +?可用于將變量轉換為數字。實例:
var y = "5"; // y 是一個字符串 var x = +y; // x 是一個數字 console.log(x)如果變量不能轉換,它仍然會是一個數字,但值為 NaN (不是一個數字)。實例:
var y = "John"; // y 是一個字符串 var x = + y; // x 是一個數字 (NaN) console.log(typeof x) console.log(x)?
將布爾值轉換為數字
全局方法?Number()?可將布爾值轉換為數字。
Number(false) // 返回 0 Number(true) // 返回 1?
將日期轉換為數字
// 全局方法 Number() 可將日期轉換為數字。 d = new Date(); console.log(Number(d)) // 返回 時間戳// 日期方法 getTime() 也有相同的效果。 d = new Date(); d.getTime() // 返回 時間戳?
自動轉換類型
當 JavaScript 嘗試操作一個 "錯誤" 的數據類型時,會自動轉換為 "正確" 的數據類型。
以下輸出結果不是你所期望的:
5?+?null????// 返回 5???????? null 轉換為 0 "5"?+?null??// 返回"5null"?? null 轉換為 "null" "5"?+?1?????// 返回 "51"????? 1 轉換為 "1"? "5"?-?1?????// 返回 4???????? "5" 轉換為 5?
自動轉換為字符串
當嘗試輸出一個對象或一個變量時 JavaScript 會自動調用變量的 toString() 方法:
// 當你嘗試輸出一個對象或一個變量時 JavaScript 會自動調用變量的 toString() 方法:document.getElementById("demo").innerHTML = myVar; myVar = {name:"Fjohn"} // toString 轉換為 "[object Object]" myVar = [1,2,3,4] // toString 轉換為 "1,2,3,4" myVar = new Date() // toString 轉換為 "Fri Jul 18 2014 09:08:55 GMT+0200"// 數字和布爾值也經常相互轉換: myVar = 123 // toString 轉換為 "123" myVar = true // toString 轉換為 "true" myVar = false // toString 轉換為 "false"下表展示了使用不同的數值轉換為數字(Number), 字符串(String), 布爾值(Boolean):
| false | 0 | "false" | false | 嘗試一下 ? |
| true | 1 | "true" | true | 嘗試一下 ? |
| 0 | 0 | "0" | false | 嘗試一下 ? |
| 1 | 1 | "1" | true | 嘗試一下 ? |
| "0" | 0 | "0" | true | 嘗試一下 ? |
| "000" | 0 | "000" | true | 嘗試一下 ? |
| "1" | 1 | "1" | true | 嘗試一下 ? |
| NaN | NaN | "NaN" | false | 嘗試一下 ? |
| Infinity | Infinity | "Infinity" | true | 嘗試一下 ? |
| -Infinity | -Infinity | "-Infinity" | true | 嘗試一下 ? |
| "" | 0 | "" | false | 嘗試一下 ? |
| "20" | 20 | "20" | true | 嘗試一下 ? |
| "Runoob" | NaN | "Runoob" | true | 嘗試一下 ? |
| [ ] | 0 | "" | true | 嘗試一下 ? |
| [20] | 20 | "20" | true | 嘗試一下 ? |
| [10,20] | NaN | "10,20" | true | 嘗試一下 ? |
| ["Runoob"] | NaN | "Runoob" | true | 嘗試一下 ? |
| ["Runoob","Google"] | NaN | "Runoob,Google" | true | 嘗試一下 ? |
| function(){} | NaN | "function(){}" | true | 嘗試一下 ? |
| { } | NaN | "[object Object]" | true | 嘗試一下 ? |
| null | 0 | "null" | false | 嘗試一下 ? |
| undefined | NaN | "undefined" | false | 嘗試一下 ? |
?
?
let 和 const 和 全局變量 和 局部變量
?
總結:
- 使用var關鍵字聲明的全局作用域變量屬于window對象。
- 使用let關鍵字聲明的全局作用域變量不屬于window對象。
- 使用var關鍵字聲明的變量在任何地方都可以修改。
- 在相同的作用域或塊級作用域中,不能使用let關鍵字來重置var關鍵字聲明的變量。
- 在相同的作用域或塊級作用域中,不能使用let關鍵字來重置let關鍵字聲明的變量。
- let關鍵字在不同作用域,或不用塊級作用域中是可以重新聲明賦值的。
- 在相同的作用域或塊級作用域中,不能使用const關鍵字來重置var和let關鍵字聲明的變量。
- 在相同的作用域或塊級作用域中,不能使用const關鍵字來重置const關鍵字聲明的變量
- const 關鍵字在不同作用域,或不同塊級作用域中是可以重新聲明賦值的:
- var關鍵字定義的變量可以先使用后聲明。
- let關鍵字定義的變量需要先聲明再使用。
- const關鍵字定義的常量,聲明時必須進行初始化,且初始化后不可再修改。
?
ECMAScript 2015(ECMAScript 6)
ES2015(ES6) 新增加了兩個重要的 JavaScript 關鍵字:?let?和?const。
- let 聲明的變量只在 let 命令所在的代碼塊內有效。
- const 聲明一個只讀的常量,一旦聲明,常量的值就不能改變。
- 在 ES6 之前,JavaScript 只有兩種作用域:?全局變量?與?函數內的局部變量。
?
全局變量
在函數外聲明的變量作用域是全局的,全局變量在 JavaScript 程序的任何地方都可以訪問。示例:
var carName = "Volvo";// 這里可以使用 carName 變量function myFunction() {// 這里也可以使用 carName 變量 }?
局部變量
函數內使用 var 聲明的變量只能在函數內容訪問,如果不使用 var 則是全局變量。
在函數內聲明的變量作用域是局部的(函數內)。示例:
// 這里不能使用 carName 變量function myFunction() {var carName = "Volvo";// 這里可以使用 carName 變量 }// 這里不能使用 carName 變量?
JavaScript 塊級作用域(Block Scope)
使用 var 關鍵字聲明的變量不具備塊級作用域的特性,它在 {} 外依然能被訪問到。
{ var x = 2; } // 這里可以使用 x 變量在 ES6 之前,是沒有塊級作用域的概念的。
ES6 可以使用 let 關鍵字來實現塊級作用域。
let 聲明的變量只在 let 命令所在的代碼塊?{}?內有效,在?{}?之外不能訪問。
?
重新定義變量
使用 var 關鍵字重新聲明變量可能會帶來問題。
在塊中重新聲明變量也會重新聲明塊外的變量:
示例:
var x = 10; // 這里輸出 x 為 10 { var x = 2;// 這里輸出 x 為 2 } // 這里輸出 x 為 2let 關鍵字就可以解決這個問題,因為它只在 let 命令所在的代碼塊?{}?內有效。
示例:
var x = 10; // 這里輸出 x 為 10 { let x = 2;// 這里輸出 x 為 2 } // 這里輸出 x 為 10?
循環作用域
使用?var?關鍵字,它聲明的變量是全局的,包括循環體內與循環體外。示例:
var i = 5; for (var i = 0; i < 10; i++) {// 一些代碼... } // 這里輸出 i 為 10使用?let?關鍵字, 它聲明的變量作用域只在循環體內,循環體外的變量不受影響。
let i = 5; for (let i = 0; i < 10; i++) {// 一些代碼... } // 這里輸出 i 為 5?
局部變量
在函數體內使用?var?和?let?關鍵字聲明的變量有點類似。
它們的作用域都是?局部的:
// 使用 var function myFunction() {var carName = "Volvo"; // 局部作用域 }// 使用 let function myFunction() {let carName = "Volvo"; // 局部作用域 }?
全局變量
在函數體外或代碼塊外使用?var?和?let?關鍵字聲明的變量也有點類似。
它們的作用域都是?全局的:
// 使用 var var x = 2; // 全局作用域// 使用 let let x = 2; // 全局作用域?
HTML 代碼中使用全局變量
- 在 JavaScript 中, 全局作用域是針對 JavaScript 環境。
- 在 HTML 中, 全局作用域是針對 window 對象。使用?var?關鍵字聲明的全局作用域變量屬于 window 對象:
示例:(?示例:嘗試一下 )
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body><h2>JavaScript 全局變量</h2><p>使用 var 關鍵字聲明的全局作用域變量屬于 window 對象。</p><p id="demo"></p><script> var carName = "Volvo";// 可以使用 window.carName 訪問變量 document.getElementById("demo").innerHTML = "I can display " + window.carName; </script></body> </html>使用?let?關鍵字聲明的全局作用域變量不屬于 window 對象。示例:嘗試一下
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body><h2>JavaScript 全局變量</h2><p>使用 let 關鍵字聲明的全局作用域變量不屬于 window 對象。</p><p id="demo"></p><script> let carName = "Volvo";// 不能使用 window.carName 訪問變量 document.getElementById("demo").innerHTML = "I can not display " + window.carName; </script></body> </html>?
重置變量
使用?var?關鍵字聲明的變量在任何地方都可以修改:
var x = 2; // x 為 2 var x = 3; // 現在 x 為 3在相同的作用域或塊級作用域中,不能使用?let?關鍵字來重置?var?關鍵字聲明的變量:
var x = 2; // 合法 let x = 3; // 不合法{var x = 4; // 合法let x = 5 // 不合法 }在相同的作用域或塊級作用域中,不能使用?let?關鍵字來重置?let?關鍵字聲明的變量:
let x = 2; // 合法 let x = 3; // 不合法{let x = 4; // 合法let x = 5; // 不合法 }在相同的作用域或塊級作用域中,不能使用?var?關鍵字來重置?let?關鍵字聲明的變量:
let x = 2; // 合法 var x = 3; // 不合法{let x = 4; // 合法var x = 5; // 不合法 }let?關鍵字在不同作用域,或不同塊級作用域中是可以重新聲明賦值的:
let x = 2; // 合法{let x = 3; // 合法 }{let x = 4; // 合法 }?
const 關鍵字
const 用于聲明一個或多個常量,聲明時必須進行初始化,且初始化后值不可再修改。示例:
const PI = 3.141592653589793; PI = 3.14; // 報錯 PI = PI + 10; // 報錯const?定義常量與使用?let? 定義的變量相似:
- 二者都是塊級作用域
- 都不能和它所在作用域內的其他變量或函數擁有相同的名稱
兩者還有以下兩點區別:
- const聲明的常量必須初始化,而let聲明的變量不用
- const 定義常量的值不能通過再賦值修改,也不能再次聲明。而 let 定義的變量值可以修改。
const 聲明的常量必須初始化:
// 錯誤寫法 const PI; PI = 3.14159265359;// 正確寫法 const PI = 3.14159265359;?
并非真正的常量
可以看理解為指針,指向的地址不能變,但是地址里面的內容是可以變化的
const 的本質: const 定義的變量并非常量,并非不可變,它定義了一個常量引用一個值。使用 const 定義的對象或者數組,其實是可變的。
下面的代碼并不會報錯:
// 創建常量對象 const car = {type:"Fiat", model:"500", color:"white"};// 修改屬性: car.color = "red";// 添加屬性 car.owner = "Johnson";但是我們不能對常量對象重新賦值:
const car = {type:"Fiat", model:"500", color:"white"}; car = {type:"Volvo", model:"EX60", color:"red"}; // 錯誤以下實例修改常量數組:
// 創建常量數組 const cars = ["Saab", "Volvo", "BMW"];// 修改元素 cars[0] = "Toyota";// 添加元素 cars.push("Audi");但是我們不能對常量數組重新賦值:
const cars = ["Saab", "Volvo", "BMW"]; cars = ["Toyota", "Volvo", "Audi"]; // 錯誤?
重置變量
使用?var?關鍵字聲明的變量在任何地方都可以修改:
示例:
var x = 2; // 合法 var x = 3; // 合法 x = 4; // 合法在相同的作用域或塊級作用域中,不能使用?const?關鍵字來重置?var?和?let關鍵字聲明的變量:
var x = 2; // 合法 const x = 2; // 不合法 {let x = 2; // 合法const x = 2; // 不合法 }在相同的作用域或塊級作用域中,不能使用?const?關鍵字來重置?const?關鍵字聲明的變量:
const x = 2; // 合法 const x = 3; // 不合法 x = 3; // 不合法 var x = 3; // 不合法 let x = 3; // 不合法{const x = 2; // 合法const x = 3; // 不合法x = 3; // 不合法var x = 3; // 不合法let x = 3; // 不合法 }const?關鍵字在不同作用域,或不同塊級作用域中是可以重新聲明賦值的:
const x = 2; // 合法{const x = 3; // 合法 }{const x = 4; // 合法 }?
變量提升
JavaScript var 關鍵字定義的變量可以在使用后聲明,也就是變量可以先使用再聲明(JavaScript 變量提升)。
carName = "Volvo"; // 這里可以使用 carName 變量 var carName;const 關鍵字定義的變量則不可以在使用后聲明,也就是變量需要先聲明再使用。
carName = "Volvo"; // 在這里不可以使用 carName 變量 const carName = "Volvo";?
?
JavaScript?函數
?
函數就是包裹在花括號中的代碼塊,前面使用了關鍵詞 function:
function?functionname() {// 執行代碼 }當調用該函數時,會執行函數內的代碼。
?
調用帶參數的函數
在調用函數時,可以向函數傳遞值,這些值被稱為參數。這些參數可以在函數中使用。可以發送任意多的參數,由逗號 (,) 分隔:
myFunction(argument1,argument2)當聲明函數時,請把參數作為變量來聲明:
function myFunction(var1,var2) {// 代碼 }變量和參數必須以一致的順序出現。第一個變量就是第一個被傳遞的參數的給定的值,以此類推。實例:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body><p>點擊這個按鈕,來調用帶參數的函數。</p> <button onclick="myFunction('Harry Potter','Wizard')">點擊這里</button> <script> function myFunction(name,job){alert("Welcome " + name + ", the " + job); } </script></body> </html>上面的函數在按鈕被點擊時會提示 "Welcome Harry Potter, the Wizard"。
?
局部 JavaScript 變量
在 JavaScript 函數內部聲明的變量(使用 var)是?局部?變量,所以只能在函數內部訪問它。(該變量的作用域是局部的)。
您可以在不同的函數中使用名稱相同的局部變量,因為只有聲明過該變量的函數才能識別出該變量。只要函數運行完畢,本地變量就會被刪除。
?
全局 JavaScript 變量
在函數外聲明的變量是?全局?變量,網頁上的所有腳本和函數都能訪問它。
?
JavaScript 變量的生存期
- JavaScript 變量的生命期從它們被聲明的時間開始。
- 局部變量會在函數運行以后被刪除。
- 全局變量會在頁面關閉后被刪除。
?
向未聲明的 JavaScript 變量分配值
如果您把值賦給尚未聲明的變量,該變量將被自動作為 window 的一個屬性。
這條語句:
carname="Volvo"; // 將聲明 window 的一個屬性 carname。非嚴格模式下給未聲明變量賦值創建的全局變量,是全局對象的可配置屬性,可以刪除。
var var1 = 1; // 不可配置全局屬性 var2 = 2; // 沒有使用 var 聲明,可配置全局屬性console.log(this.var1); // 1 console.log(window.var1); // 1 console.log(window.var2); // 2delete var1; // false 無法刪除 console.log(var1); //1delete var2; console.log(delete var2); // true console.log(var2); // 已經刪除 報錯變量未定義?
?
JavaScript?作用域
?
JavaScript 局部作用域
變量在函數內聲明,變量為局部作用域。局部變量:只能在函數內部訪問。
function myFunction() {var carName = "Volvo";// 函數內可調用 carName 變量 } // 此處不能調用 carName 變量 console.log(carName)因為局部變量只作用于函數內,所以不同的函數可以使用相同名稱的變量。
局部變量在函數開始執行時創建,函數執行完后局部變量會自動銷毀。
?
JavaScript 全局變量
變量在函數外定義,即為全局變量。全局變量有?全局作用域:?網頁中所有腳本和函數均可使用。?
var carName = "Volvo";// 此處可調用 carName 變量 function myFunction() {// 函數內可調用 carName 變量console.log(carName) } myFunction()如果變量在函數內沒有聲明(沒有使用 var 關鍵字),該變量為全局變量。以下實例中 carName 在函數內,但是為全局變量。
// 此處可調用 carName 變量 function myFunction() {// 函數內可調用 carName 變量carName = "Volvo";console.log(carName) } myFunction() console.log(carName)?
JavaScript 變量生命周期
- JavaScript 變量生命周期在它聲明時初始化。
- 局部變量在函數執行完畢后銷毀。函數參數只在函數內起作用,是局部變量。
- 全局變量在頁面關閉后銷毀。在 HTML 中, 全局變量是 window 對象: 所有數據變量都屬于 window 對象。
注意:你的全局變量,或者函數,可以覆蓋 window 對象的變量或者函數。局部變量,包括 window 對象可以覆蓋全局變量和函數。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body><p> 在 HTML 中, 所有全局變量都會成為 window 變量。 </p> <p id="demo"></p> <script> myFunction(); document.getElementById("demo").innerHTML ="我可以顯示 " + window.carName; function myFunction() {carName = "Volvo"; } </script></body> </html>?
?
JavaScript 代碼規范
?
規范的代碼可以更易于閱讀與維護。代碼規范一般在開發前規定,可以跟你的團隊成員來協商設置。
代碼規范通常包括以下幾個方面:
- 變量 和 函數 的命名規則
- 空格,縮進,注釋?的使用規則。
- 其他常用規范……
變量名。變量名推薦使用駝峰法來命名(camelCase):
firstName = "John"; lastName = "Doe"; price = 19.90; tax = 0.20; fullPrice = price + (price * tax);空格與運算符。通常運算符 ( = + - * / ) 前后需要添加空格。實例:
var?x = y + z; var?values = ["Volvo",?"Saab",?"Fiat"];代碼縮進。通常使用 4 個空格符號來縮進代碼塊。不推薦使用 TAB 鍵來縮進,因為不同編輯器 TAB 鍵的解析不一樣。函數縮進:
function toCelsius(fahrenheit) {return (5 / 9) * (fahrenheit - 32); }語句規則。簡單語句的通用規則:一條語句通常以分號作為結束符。實例:
varvalues = ["Volvo", "Saab", "Fiat"];varperson = {firstName: "John",lastName: "Doe",age: 50,eyeColor: "blue" };復雜語句的通用規則:
- 將左花括號放在第一行的結尾。
- 左花括號前添加一空格。
- 將右花括號獨立放在一行。
- 不要以分號結束一個復雜的聲明。
函數:
function toCelsius(fahrenheit) {return (5 / 9) * (fahrenheit - 32); }toCelsius()var x=0, y; for (var i = 0; i < 5; i++) {x += i;console.log(x.toString())console.log(y) }var time = 10 if (time < 20) {greeting = "Good day"; } else {greeting = "Good evening"; } console.log(greeting)對象定義的規則:
- 將左花括號與類名放在同一行。
- 冒號與屬性值間有個空格。
- 字符串使用雙引號,數字不需要。
- 最后一個屬性-值對后面不要添加逗號。
- 將右花括號獨立放在一行,并以分號作為結束符號。
實例:
var person = {firstName: "John",lastName: "Doe",age: 50,eyeColor: "blue" };短的對象代碼可以直接寫成一行。實例:
var person = {firstName: "John", lastName: "Doe", age: 50, eyeColor: "blue"};命名規則
一般很多代碼語言的命名規則都是類似的,例如:
- 變量和函數為小駝峰法標識, 即除第一個單詞之外,其他單詞首字母大寫(?lowerCamelCase)
- 全局變量為大寫 (UPPERCASE?)
- 常量 (如 PI) 為大寫 (UPPERCASE?)
變量命名你是否使用這幾種規則:?hyp-hens,?camelCase, 或?under_scores??
HTML 和 CSS 的橫杠(-)字符:
HTML5 屬性可以以 data- (如:data-quantity, data-price) 作為前綴。
CSS 使用 - 來連接屬性名 (font-size)。
- 通常在 JavaScript 中被認為是減法,所以不允許使用。
變量名不要以 $ 作為開始標記,會與很多 JavaScript 庫沖突。
下劃線:
- 很多程序員比較喜歡使用下劃線(如:date_of_birth), 特別是在 SQL 數據庫中。PHP 語言通常都使用下劃線。
- 帕斯卡拼寫法(PascalCase):帕斯卡拼寫法(PascalCase) 在 C 語言中語言較多。
- 駝峰法:JavaScript 中通常推薦使用駝峰法,jQuery 及其他 JavaScript 庫都使用駝峰法。
HTML 載入外部 JavaScript 文件
使用簡潔的格式載入 JavaScript 文件 ( type 屬性不是必須的):<script?src="myscript.js">
使用 JavaScript 訪問 HTML 元素
一個糟糕的 HTML 格式可能會導致 JavaScript 執行錯誤。以下兩個 JavaScript 語句會輸出不同結果。實例:
var?obj = getElementById("Demo")
var?obj = getElementById("demo")
嘗試一下 ?
HTML 與 JavaScript 盡量使用相同的命名規則。訪問 HTML(5) 代碼規范。
文件擴展名
- HTML 文件后綴可以是?.html?(或?.htm)。
- CSS 文件后綴是?.css?。
- JavaScript 文件后綴是?.js?。
使用小寫文件名
- 大多 Web 服務器 (Apache, Unix) 對大小寫敏感: london.jpg 不能通過 London.jpg 訪問。
- 其他 Web 服務器 (Microsoft, IIS) 對大小寫不敏感: london.jpg 可以通過 London.jpg 或 london.jpg 訪問。
- 你必須保持統一的風格,建議統一使用小寫的文件名。
?
?
JavaScript?事件
?
HTML 事件是發生在 HTML 元素上的事情。當在 HTML 頁面中使用 JavaScript 時, JavaScript 可以觸發這些事件。
HTML 事件可以是瀏覽器行為,也可以是用戶行為。以下是 HTML 事件的實例:
- HTML 頁面完成加載
- HTML input 字段改變時
- HTML 按鈕被點擊
通常,當事件發生時,你可以做些事情。在事件觸發時 JavaScript 可以執行一些代碼。
HTML 元素中可以添加事件屬性,使用 JavaScript 代碼來添加 HTML 元素。
- 單引號:<some-HTML-element?some-event='JavaScript 代碼'>
- 雙引號:<some-HTML-element?some-event="JavaScript 代碼">
按鈕元素中添加了 onclick 屬性:<button οnclick="getElementById('demo').innerHTML=Date()">現在的時間是?</button>
代碼將修改自身元素的內容 (使用?this.innerHTML):<button οnclick="this.innerHTML=Date()">現在的時間是?</button>
?
常見的 HTML 事件
下面是一些常見的HTML事件的列表:
| onchange | HTML 元素改變 |
| onclick | 用戶點擊 HTML 元素 |
| onmouseover | 用戶在一個HTML元素上移動鼠標 |
| onmouseout | 用戶從一個HTML元素上移開鼠標 |
| onkeydown | 用戶按下鍵盤按鍵 |
| onload | 瀏覽器已完成頁面的加載 |
更多事件列表:?JavaScript 參考手冊 - HTML DOM 事件。
?
JavaScript 可以做什么?
事件可以用于處理表單驗證,用戶輸入,用戶行為及瀏覽器動作:
- 頁面加載時觸發事件
- 頁面關閉時觸發事件
- 用戶點擊按鈕執行動作
- 驗證用戶輸入內容的合法性
- 等等 ...
可以使用多種方法來執行 JavaScript 事件代碼:
- HTML 事件屬性可以直接執行 JavaScript 代碼
- HTML 事件屬性可以調用 JavaScript 函數
- 你可以為 HTML 元素指定自己的事件處理程序
- 你可以阻止事件的發生。
- 等等 ...
在 HTML DOM 章節中你將會學到更多關于事件及事件處理程序的知識。
?
?
JavaScript?字符串
?
字符串用于存儲和處理文本。
- 字符串可以是插入到引號中的任何字符。可以使用 單引號 或 雙引號。
- 字符串的索引從 0 開始,這意味著第一個字符索引值為 [0],第二個為 [1],?以此類推。
可以在字符串中使用引號,字符串中的引號不要與字符串的引號相同,實例:
var answer = "It's alright"; var answer = "He is called 'Johnny'"; var answer = 'He is called "Johnny"';你也可以在字符串添加轉義字符來使用引號。實例:
var x = 'It\'s alright'; var y = "He is called \"Johnny\"";?
字符串長度
可以使用內置屬性?length?來計算字符串的長度:
var txt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; var txt_len = txt.length; console.log('txt_len = ' + txt_len) for (var i = 0; i < txt_len; i++) {console.log(txt[i]) }?
特殊字符
在 JavaScript 中,字符串寫在單引號或雙引號中。因為這樣,以下實例 JavaScript 無法解析:?"We are the so-called "Vikings" from the north."
字符串 "We are the so-called " 被截斷。
如何解決以上的問題呢?可以使用反斜杠 (\) 來轉義 "Vikings" 字符串中的雙引號,如下:?"We are the so-called \"Vikings\" from the north."
?反斜杠是一個轉義字符。 轉義字符將特殊字符轉換為字符串字符。轉義字符 (\) 可以用于轉義撇號,換行,引號,等其他特殊字符。
下表中列舉了在字符串中可以使用轉義字符轉義的特殊字符:
| \' | 單引號 |
| \" | 雙引號 |
| \\ | 反斜杠 |
| \n | 換行 |
| \r | 回車 |
| \t | tab(制表符) |
| \b | 退格符 |
| \f | 換頁符 |
?
字符串可以是對象
- 通常, JavaScript 字符串是原始值,可以使用字符創建:?var firstName = "John"
- 但我們也可以使用 new 關鍵字將字符串定義為一個對象:?var firstName = new String("John")
注意:不要創建 String 對象。它會拖慢執行速度,并可能產生其他副作用。(?=== 為絕對相等,即數據類型與值都必須相等。 )
var x = "John"; var y = new String("John"); var bval = (x === y) // 結果為 false,因為 x 是字符串,y 是對象 console.log(bval) // 輸出結果 false?
字符串屬性和方法
原始值字符串,如 "John", 沒有屬性和方法(因為他們不是對象)。
原始值可以使用 JavaScript 的屬性和方法,因為 JavaScript 在執行方法和屬性時可以把原始值當作對象。
字符串方法我們將在下一章節中介紹。
?
字符串屬性
| constructor | 返回創建字符串屬性的函數 |
| length | 返回字符串的長度 |
| prototype | 允許您向對象添加屬性和方法 |
?
字符串方法
更多方法實例可以參見:JavaScript String 對象。
| charAt() | 返回指定索引位置的字符 |
| charCodeAt() | 返回指定索引位置字符的 Unicode 值 |
| concat() | 連接兩個或多個字符串,返回連接后的字符串 |
| fromCharCode() | 將 Unicode 轉換為字符串 |
| indexOf() | 返回字符串中檢索指定字符第一次出現的位置 |
| lastIndexOf() | 返回字符串中檢索指定字符最后一次出現的位置 |
| localeCompare() | 用本地特定的順序來比較兩個字符串 |
| match() | 找到一個或多個正則表達式的匹配 |
| replace() | 替換與正則表達式匹配的子串 |
| search() | 檢索與正則表達式相匹配的值 |
| slice() | 提取字符串的片斷,并在新的字符串中返回被提取的部分 |
| split() | 把字符串分割為子字符串數組 |
| substr() | 從起始索引號提取字符串中指定數目的字符 |
| substring() | 提取字符串中兩個指定的索引號之間的字符 |
| toLocaleLowerCase() | 根據主機的語言環境把字符串轉換為小寫,只有幾種語言(如土耳其語)具有地方特有的大小寫映射 |
| toLocaleUpperCase() | 根據主機的語言環境把字符串轉換為大寫,只有幾種語言(如土耳其語)具有地方特有的大小寫映射 |
| toLowerCase() | 把字符串轉換為小寫 |
| toString() | 返回字符串對象值 |
| toUpperCase() | 把字符串轉換為大寫 |
| trim() | 移除字符串首尾空白 |
| valueOf() | 返回某個字符串對象的原始值 |
?
?
JavaScript?運算符
?
運算符優先級:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
運算符 = 用于賦值。運算符 = 用于給 JavaScript 變量賦值。
運算符 + 用于加值。算術運算符 + 用于把值加起來。
實例:指定變量值,并將值相加:
y = 5; z = 2; x = y + z; //執行后,x 的值是 7?
JavaScript 算術運算符
| + | 加法 | x=y+2 | 7 | 5 | 實例 ? |
| - | 減法 | x=y-2 | 3 | 5 | 實例 ? |
| * | 乘法 | x=y*2 | 10 | 5 | 實例 ? |
| / | 除法 | x=y/2 | 2.5 | 5 | 實例 ? |
| % | 取模(余數) | x=y%2 | 1 | 5 | 實例 ? |
| ++ | 自增 | x=++y | 6 | 6 | 實例 ? |
| x=y++ | 5 | 6 | 實例 ? | ||
| -- | 自減 | x=--y | 4 | 4 | 實例 ? |
| x=y-- | 5 | 4 | 實例 ? |
?
JavaScript 賦值運算符
賦值運算符用于給 JavaScript 變量賦值。賦值運算符:
| = | x=y | ? | x=5 | 實例 ? |
| += | x+=y | x=x+y | x=15 | 實例 ? |
| -= | x-=y | x=x-y | x=5 | 實例 ? |
| *= | x*=y | x=x*y | x=50 | 實例 ? |
| /= | x/=y | x=x/y | x=2 | 實例 ? |
| %= | x%=y | x=x%y | x=0 | 實例 ? |
?
用于字符串的 + 運算符
+ 運算符用于把文本值或字符串變量加起來(連接起來)。如需把兩個或多個字符串變量連接起來,請使用 + 運算符。
實例:如需把兩個或多個字符串變量連接起來,請使用 + 運算符:
txt1 = "What a very"; txt2 = "nice day"; txt3 = txt1 + txt2; // txt3 值為 What a verynice day?
字符串和數字進行加法運算
規則:如果把數字與字符串相加,結果將成為字符串!
兩個數字相加,返回數字相加的和,如果數字與字符串相加,返回字符串,如下實例:
x = 5 + 5; // x 值為 10 y = "5" + 5; // y 值為 55 z = "Hello" + 5; // z 值為 Hello5 a = 123 + 'hello' // a 值為 123hello?
?
JavaScript?比較?和?邏輯 運算符
?
比較和邏輯運算符用于測試?true?或者?false。
?
比較運算符
比較運算符在邏輯語句中使用,以測定變量或值是否相等。比較運算符:
| == | 等于 | x==8 | false | 實例 ? |
| x==5 | true | 實例 ? | ||
| === | 絕對等于(值和類型均相等) | x==="5" | false | 實例 ? |
| x===5 | true | 實例 ? | ||
| != | ?不等于 | x!=8 | true | 實例 ? |
| !== | ?不絕對等于(值和類型有一個不相等,或兩個都不相等) | x!=="5" | true | 實例 ? |
| x!==5 | false | 實例 ? | ||
| > | ?大于 | x>8 | false | 實例 ? |
| < | ?小于 | x<8 | true | 實例 ? |
| >= | ?大于或等于 | x>=8 | false | 實例 ? |
| <= | ?小于或等于 | x<=8 | true | 實例 ? |
?
?
邏輯運算符
邏輯運算符用于測定變量或值之間的邏輯。邏輯運算符:
| && | and | (x < 10 && y > 1) 為 true |
| || | or | (x==5 || y==5) 為 false |
| ! | not | !(x==y) 為 true |
注意:
- &? ? 按 位 與
- |? ? ?按 位?或??
?
?
條件運算符
JavaScript 還包含了基于某些條件對變量進行賦值的條件運算符。
語法:variablename?= (condition)?value1:value2;
//如果變量 age 中的值小于 18,則向變量 voteable 賦值 "年齡太小",否則賦值 "年齡已達到"。 voteable = (age < 18) ? "年齡太小" : "年齡已達到";?
?
JavaScript 語句
?
if else 條件語句
條件語句用于基于不同的條件來執行不同的動作。
在寫代碼時,需要為不同的決定來執行不同的動作。可以在代碼中使用條件語句來完成該任務。
在 JavaScript 中,我們可使用以下條件語句:
- if 語句? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ----- 只有當指定條件為 true 時,使用該語句來執行代碼
- if...else 語句? ? ? ? ? ? ? ? ? ? ----- 當條件為 true 時執行代碼,當條件為 false 時執行其他代碼
- if...else if....else 語句? ? ?----- 使用該語句來選擇多個代碼塊之一來執行
- switch 語句? ? ? ? ? ? ? ? ? ? ?----- 使用該語句來選擇多個代碼塊之一來執行
?
switch?語句
switch 語句用于基于不同的條件來執行不同的動作。
switch(n) {case 1:// 執行代碼塊 1break;case 2:// 執行代碼塊 2break;default:// 與 case 1 和 case 2 不同時執行的代碼 }工作原理:首先設置表達式?n(通常是一個變量)。隨后表達式的值會與結構中的每個 case 的值做比較。如果存在匹配,則與該 case 關聯的代碼塊會被執行。請使用?break?來阻止代碼自動地向下一個 case 運行。
實例:顯示今天的星期名稱。請注意 Sunday=0, Monday=1, Tuesday=2, 等等:
var d = new Date().getDay(); switch (d) {case 0:x = "今天是星期日";break;case 1:x = "今天是星期一";break;case 2:x = "今天是星期二";break;case 3:x = "今天是星期三";break;case 4:x = "今天是星期四";break;case 5:x = "今天是星期五";break;case 6:x = "今天是星期六";break; } console.log(x)default 關鍵詞來規定匹配不存在時做的事情:
var d = new Date().getDay(); switch (d) {case 6:x = "今天是星期六";break;case 0:x = "今天是星期日";break;default:x = "期待周末"; } console.log(x)?
for 循環
JavaScript 支持不同類型的循環:
- for?- 循環代碼塊一定的次數
- for/in?- 循環遍歷對象的屬性
- while?- 當指定的條件為 true 時循環指定的代碼塊
- do/while?- 同樣當指定的條件為 true 時循環指定的代碼塊
for 循環是您在希望創建循環時常會用到的工具。
for 循環的語法:
? ? ? ? for (語句1;?語句2;?語句3)
? ? ? ? {
? ? ? ? ????被執行的代碼塊
? ? ? ? }
說明:
? ? ? ? 語句1?(代碼塊)開始前執行
? ? ? ? 語句2?定義運行循環(代碼塊)的條件
? ? ? ? 語句3?在循環(代碼塊)已被執行之后執行
使用 for 循環
for (var i = 0; i < cars.length; i++) {document.write(cars[i] + "<br>"); } for (var i = 0; i < 5; i++) {x = x + "該數字為 " + i + "<br>"; }語句1
? ? ? ? 通常使用 語句1 初始化循環中所用的變量 (var i=0)。
? ? ? ? 語句1 是可選的,也就是說不使用 語句1 也可以。
? ? ? ? 可以在 語句1 中初始化任意(或者多個)值
語句2
? ? ? ? 通常 語句2 用于評估初始變量的條件。
? ? ? ? 如果 語句2 返回 true,則循環再次開始,如果返回 false,則循環將結束。
? ? ? ? 語句2 同樣是可選的。 ? ? ? ?
? ? ? ? 如果省略了 語句2,那么必須在循環內提供 break。否則循環就無法停下來。這樣有可能令瀏覽器崩潰。
語句3
? ? ? ? 通常 語句3 會增加初始變量的值。
? ? ? ? 語句3 也是可選的。
? ? ? ? 語句3 有多種用法。增量可以是負數 (i--),或者更大 (i=i+15)。
? ? ? ? 語句3 也可以省略(比如當循環內部有相應的代碼時)
?
for / In 循環
JavaScript 的 for / in 語句循環遍歷對象的屬性。(?在有關 JavaScript 對象的章節學到更多有關 for / in 循環的知識。 )
var person = {fname: "Bill", lname: "Gates", age: 56};var txt = ''; for (x in person) // x 為屬性名 {txt = txt + person[x]; } console.log(txt)?
while 循環
while 循環會在指定條件為真時循環執行代碼塊。
語法:
? ? ? ? while (條件)
? ? ? ? {
? ? ? ? ????// 需要執行的代碼
? ? ? ? }
實例:本例中的循環將繼續運行,只要變量 i 小于 5:
var i = 1, x = ''; while (i < 5) {x = x + "The number is " + i + "<br>" + '\n';i++; } console.log(x)?
do/while 循環
do/while 循環是 while 循環的變體。該循環會在檢查條件是否為真之前執行一次代碼塊,然后如果條件為真的話,就會重復這個循環。
語法:
? ? ? ? do
? ? ? ? {
? ? ? ? ????// 需要執行的代碼
? ? ? ? }
? ? ? ? while (條件);
實例:下面的例子使用 do/while 循環。該循環至少會執行一次,即使條件為 false 它也會執行一次,因為代碼塊會在條件被測試前執行:
var x = ''; do {x = x + "The number is " + i + "<br>";i++; } while (i < 5);?
比較 for 和 while
while 循環與 for 循環很像。
使用?for 循環來顯示 cars 數組中的所有值:
cars = ["BMW", "Volvo", "Saab", "Ford"]; var i = 0; for (; cars[i];) {document.write(cars[i] + "<br>");i++; }使用?while 循環來顯示 cars 數組中的所有值:
cars = ["BMW", "Volvo", "Saab", "Ford"]; var i = 0; while (cars[i]) {document.write(cars[i] + "<br>");i++; }?
break 和 continue 語句
- break 語句用于跳出循環。
- continue 用于跳過循環中的一個迭代。
?
?
typeof, null, 和 undefined
?
typeof
typeof 操作符:你可以使用 typeof 操作符來檢測變量的數據類型。
在JavaScript中,數組是一種特殊的對象類型。 因此 typeof [1,2,3,4] 返回 object。?
console.log(typeof "John") // 返回 string console.log(typeof 3.14) // 返回 number console.log(typeof false) // 返回 boolean console.log(typeof [1,2,3,4]) // 返回 object console.log(typeof {name:'John', age:34}) // 返回 object?
null
在 JavaScript 中 null 表示 "什么都沒有"。
null 是一個只有一個值的特殊類型。表示一個空對象引用。用 typeof 檢測 null 返回是object。
可以設置為 null 來清空對象:
var?person =?null;???????????// 值為 null(空), 但類型為對象?
undefined
在 JavaScript 中,?undefined?是一個沒有設置值的變量。typeof?一個沒有值的變量會返回?undefined。
var person; // 值為 undefined(空), 類型是undefined任何變量都可以通過設置值為?undefined?來清空。 類型為?undefined.
person = undefined; // 值為 undefined, 類型是undefined?
undefined 和 null 的區別
null 和 undefined 的值相等,但類型不等
typeof undefined // undefined typeof null // object null === undefined // false (=== 表示絕對相等:"值"和"類型"都相等) null == undefined // true (== 表示值相等)1、定義
- ?(1)undefined:是所有沒有賦值變量的默認值,自動賦值。
- ?(2)null:主動釋放一個變量引用的對象,表示一個變量不再指向任何對象地址。
2、何時使用null?
當使用完一個比較大的對象時,需要對其進行釋放內存時,設置為 null。
3、null 與 undefined 的異同點是什么呢?
共同點:都是原始類型,保存在棧中變量本地。
不同點:
- (1)undefined :?表示變量聲明過但并未賦過值。它是所有未賦值變量默認值,例如:var a; // a 自動被賦值為 undefined
- (2)null :表示一個變量將來可能指向一個對象。一般用于主動釋放指向對象的引用,例如:var emps = ['ss','nn']; emps = null; // 釋放指向數組的引用
4、延伸 ----- 垃圾回收站
它是專門釋放對象內存的一個程序。
- ?(1)在底層,后臺伴隨當前程序同時運行;引擎會定時自動調用垃圾回收期;
- ?(2)總有一個對象不再被任何變量引用時,才釋放。
?
?
JavaScript?正則表達式
?
JS正則表達式語法大全(非常詳細):http://c.biancheng.net/view/5632.html
JS正則表達式完整版:https://blog.csdn.net/h610443955/article/details/81079439
JavaScript 正則表達式:https://www.runoob.com/js/js-regexp.html
語法(其中修飾符是可選的):/正則表達式主體/修飾符(可選)
實例:var patt = /runoob/i
實例解析:
- /runoob/i? 是一個正則表達式。
- runoob? 是一個正則表達式主體?(用于檢索)。
- i? 是一個修飾符?(搜索不區分大小寫)。
?
字符串方法?search 和?replace
在 JavaScript 中,正則表達式通常用于兩個字符串方法 : search() 和 replace()。
- search() 方法?用于檢索字符串中指定的子字符串,或檢索與正則表達式相匹配的子字符串,并返回子串的起始位置。
- replace() 方法?用于在字符串中用一些字符替換另一些字符,或替換一個與正則表達式匹配的子串。
search() 方法 和 replace() 方法 使用正則表達式:
// 使用正則表達式搜索 "Runoob" 字符串,且不區分大小寫: var str = "Visit Runoob!"; var str_index = str.search(/Runoob/i); console.log(str_index)// 使用正則表達式且不區分大小寫將字符串中的 Microsoft 替換為 Runoob : // var str = document.getElementById("demo").innerHTML; var str = 'this is a [microsoft] test' var txt = str.replace(/microsoft/i, "Runoob"); console.log(txt)使用字符串作為參數時,字符串參數會轉換為正則表達式:
// 檢索字符串中 "Runoob" 的子串: var str = "Visit Runoob!"; var n = str.search("Runoob");var str = document.getElementById("demo").innerHTML; var txt = str.replace("Microsoft","Runoob");?
正則表達式修飾符
修飾符?可以在全局搜索中不區分大小寫:
| i | 執行對大小寫不敏感的匹配。 |
| g | 執行全局匹配(查找所有匹配而非在找到第一個匹配后停止)。 |
| m | 執行多行匹配。 |
正則表達式模式
方括號用于查找某個范圍內的字符:
| [abc] | 查找方括號之間的任何字符。 |
| [0-9] | 查找任何從 0 至 9 的數字。 |
| (x|y) | 查找任何以 | 分隔的選項。 |
元字符是擁有特殊含義的字符:
| \d | 查找數字。 |
| \s | 查找空白字符。 |
| \b | 匹配單詞邊界。 |
| \uxxxx | 查找以十六進制數 xxxx 規定的 Unicode 字符。 |
量詞:
| n+ | 匹配任何包含至少一個?n?的字符串。 |
| n* | 匹配任何包含零個或多個?n?的字符串。 |
| n? | 匹配任何包含零個或一個?n?的字符串。 |
使用 RegExp 對象
在 JavaScript 中,RegExp 對象是一個預定義了屬性和方法的正則表達式對象。
使用 test():
test() 方法是一個正則表達式方法。
test() 方法用于檢測一個字符串是否匹配某個模式,如果字符串中含有匹配的文本,則返回 true,否則返回 false。
以下實例用于搜索字符串中的字符 "e"。實例:
var?patt = /e/; patt.test("The best things in life are free!"); // 返回 true也可以不用設置正則表達式的變量,以上兩行代碼可以合并為一行:/e/.test("The best things in life are free!")
使用 exec()
exec() 方法是一個正則表達式方法。
exec() 方法用于檢索字符串中的正則表達式的匹配。
該函數返回一個數組,其中存放匹配的結果。如果未找到匹配,則返回值為 null。
以下實例用于搜索字符串中的字母 "e":/e/.exec("The best things in life are free!");
?
示例:
var testStr = "now test001 test002"; var re = /test(\d+)/ig; var r = ""; while(r = re.exec(testStr)) {console.log(r[0] + " " + r[1]); }var tempArray = /<([^>]*?)>/.exec("<div>>測試div<span>>"); console.log("長度 : " + tempArray.length); for (var index = 0; index < tempArray.length; index++) {console.log(index + " = " + tempArray[index]); }re = "<div>>測試div<span>>".match(/<([^>]*?)>/g) console.log("長度 : " + tempArray.length); for (var index = 0; index < tempArray.length; index++) {console.log(re[index]) }?
更多實例
-
JS 判斷輸入字符串是否為數字、字母、下劃線組成
-
JS 判斷輸入字符串是否全部為字母
-
JS 判斷輸入字符串是否全部為數字
?
完整的 RegExp 參考手冊
完整的 RegExp 對象參考手冊,請參考我們的?JavaScript RegExp 參考手冊。
該參考手冊包含了所有 RegExp 對象的方法和屬性。
?
?
JavaScript 的錯誤捕獲 --- throw、try 和 catch
?
- try?語句測試代碼塊的錯誤。
- catch?語句處理錯誤。
- throw?語句創建自定義錯誤。
- finally?語句在 try 和 catch 語句之后,無論是否有觸發異常,該語句都會執行。
?
try 和 catch
try?語句允許我們定義在執行時進行錯誤測試的代碼塊。
catch?語句允許我們定義當 try 代碼塊發生錯誤時,所執行的代碼塊。
JavaScript 語句?try?和?catch?是成對出現的。
語法:
? ? ? ? try {
? ? ? ? ? ? //異常的拋出
? ? ? ? } catch(e) {
? ? ? ? ? ? //異常的捕獲與處理
? ? ? ? } finally {
? ? ? ? ? ? //結束處理
? ? ? ? }
實例:在下面的例子中,我們故意在 try 塊的代碼中寫了一個錯字。catch 塊會捕捉到 try 塊中的錯誤,并執行代碼來處理它。
var txt = "";function message() {try {adddlert("Welcome guest!");} catch (err) {txt = "本頁有一個錯誤。\n\n";txt += "錯誤描述:" + err.message + "\n\n";txt += "點擊確定繼續。\n\n";console.log(txt);} } message()?
finally 語句
finally 語句不論之前的 try 和 catch 中是否產生異常都會執行該代碼塊。
function myFunction() {var message, x;message = document.getElementById("p01");message.innerHTML = "";x = document.getElementById("demo").value;try {if(x == "") throw "值是空的";if(isNaN(x)) throw "值不是一個數字";x = Number(x);if(x > 10) throw "太大";if(x < 5) throw "太小";}catch(err) {message.innerHTML = "錯誤: " + err + ".";}finally {document.getElementById("demo").value = "";} }?
Throw 語句
throw 語句允許我們創建自定義錯誤。
正確的技術術語是:創建或拋出異常(exception)。
如果把 throw 與 try 和 catch 一起使用,那么您能夠控制程序流,并生成自定義的錯誤消息。
語法:throw?exception
異常可以是 JavaScript 字符串、數字、邏輯值或對象。
實例:本例檢測輸入變量的值。如果值是錯誤的,會拋出一個異常(錯誤)。catch 會捕捉到這個錯誤,并顯示一段自定義的錯誤消息:
function myFunction() {var message, x;message = document.getElementById("message");message.innerHTML = "";x = document.getElementById("demo").value;try {if(x == "") throw "值為空";if(isNaN(x)) throw "不是數字";x = Number(x);if(x < 5) throw "太小";if(x > 10) throw "太大";}catch(err) {message.innerHTML = "錯誤: " + err;} }?
?
JavaScript?使用誤區
?
賦值運算符應用錯誤
在 JavaScript 程序中如果你在 if 條件語句中使用賦值運算符的等號 (=) 將會產生一個錯誤結果,?正確的方法是使用比較運算符的兩個等號 (==)。
if?條件語句返回?false?(是我們預期的) 因為 x 不等于 10:
var x = 0; if (x == 10){console.log("相等"); }else {console.log("不相等"); }?
比較運算符常見錯誤
在常規的比較中,數據類型 是 被忽略的,以下 if 條件語句返回 true:
var x = 10; var y = "10"; if (x == y){console.log("相等"); }else {console.log("不相等"); }在嚴格的比較運算中,=== 為恒等計算符,同時檢查表達式的 值 與 類型,以下 if 條件語句返回 false:
var x = 10; var y = "10"; if (y === x){console.log("相等"); }else {console.log("不相等"); }這種錯誤經常會在 switch 語句中出現,switch 語句會使用恒等計算符(===)進行比較:
?
加法與連接注意事項
加法?是兩個數字相加。
連接?是兩個字符串?連接。
JavaScript 的加法和連接都使用 + 運算符。
接下來我們可以通過實例查看 兩個數字相加 及 數字與字符串連接 的區別:
var x = 10 + 5; // x 的結果為 15 var x = 10 + "5"; // x 的結果為 "105"使用變量相加結果也不一致:
var x = 10; var y = 5; var z = x + y; // z 的結果為 15var x = 10; var y = "5"; var z = x + y; // z 的結果為 "105"?
浮點型數據使用注意事項
JavaScript 中的所有數據都是以 64 位浮點型數據(float)?來存儲。
所有的編程語言,包括 JavaScript,對浮點型數據的精確度都很難確定:
var x = 0.1; var y = 0.2; var z = x + y // z 的結果為 0.30000000000000004 if (z == 0.3) // 返回 false為解決以上問題,可以用整數的乘除法來解決:
var z = (x * 10 + y * 10) / 10; // z 的結果為 0.3更多內容可以參考:JavaScript 中精度問題以及解決方案
?
JavaScript 字符串分行
JavaScript 允許我們在字符串中使用斷行語句:
正確示例:
var x = "Hello World!";錯誤示例:在字符串中直接使用回車換行是會報錯的:
var x = "Hello World!";正確示例:字符串斷行需要使用反斜杠(\),如下所示:
var x = "Hello \ World!";?
錯誤的使用分號
在 JavaScript 中,分號是可選的 。
由于 return 是一個完整的語句,所以 JavaScript 將關閉 return 語句。
以下實例中,if 語句失去方法體,原 if 語句的方法體作為獨立的代碼塊被執行,導致錯誤的輸出結果。
由于分號使用錯誤,if 語句中的代碼塊就一定會執行:
if (x == 19); {// code block }?
return 語句使用注意事項
JavaScript 默認是在代碼的最后一行自動結束。
以下兩個實例返回結果是一樣的 ( 一個有分號,一個沒有 ):
實例 1 :( 沒有分號?)
function?myFunction(a) {var?power =?10?return?a * power }實例 2 ( 有分號 )
function?myFunction(a) {var?power =?10;return?a * power; }JavaScript 也可以使用多行來結束一個語句。以下實例返回相同的結果。示例 3
function myFunction(a) {varpower = 10; return a * power; }?
數組中使用名字來索引 ( 錯誤用法?)
- 許多程序語言都允許使用名字來作為數組的索引。使用名字來作為索引的數組稱為 關聯數組 (或 哈希 )。
- JavaScript 不支持使用名字來索引數組,只允許使用數字索引。
實例
var person = []; person[0] = "John"; person[1] = "Doe"; person[2] = 46; var x = person.length; // person.length 返回 3 var y = person[0]; // person[0] 返回 "John"?
在 JavaScript 中,?對象?使用?名字作為索引。
當訪問數組時,如果使用名字作為索引,JavaScript 會把數組重新定義為標準對象。執行這樣操作后,數組的方法及屬性將不能再使用,否則會產生錯誤:
var person = []; person["firstName"] = "John"; person["lastName"] = "Doe"; person["age"] = 46; var x = person.length; // person.length 返回 0 var y = person[0]; // person[0] 返回 undefined?
定義數組元素,最后不能添加逗號
數組最后一個值的后面添加逗號雖然語法沒有問題,但是在不同的瀏覽器可能得到不同的結果。
- 錯誤的方式:var colors = [5, 6, 7,];? ? // 這樣數組的長度可能為3 也可能為4。
- 正確的定義方式:points = [40, 100, 1, 5, 25, 10];
?
定義對象,最后不能添加逗號
- 錯誤的定義方式:websites = {site:"菜鳥教程", url:"www.runoob.com", like:460,}
- 正確的定義方式:websites = {site:"菜鳥教程", url:"www.runoob.com", like:460}
?
Undefined 不是 Null
在 JavaScript 中,?
- null?用于 對象
- undefined?用于變量,屬性和方法。
對象只有被定義才有可能為 null,否則為 undefined。
如果我們想測試對象是否存在,在對象還沒定義時將會拋出一個錯誤。
- 錯誤的使用方式:if (myObj !== null && typeof myObj !== "undefined")
- 正確的方式是先使用 typeof 來檢測對象是否已定義:if (typeof myObj !== "undefined" && myObj !== null)
?
程序塊作用域
在每個代碼塊中 JavaScript 不會創建一個新的作用域,一般各個代碼塊的作用域都是全局的。
以下代碼的的變量 i 返回 10,而不是 undefined:
for (var i = 0; i < 10; i++) {// some code } return i;?
?
JavaScript 表單
?
JavaScript 表單驗證
HTML 表單驗證可以通過 JavaScript 來完成。
以下實例代碼用于判斷表單字段(fname)值是否存在, 如果不存在,就彈出信息,阻止表單提交:
JavaScript 實例
function validateForm() {var x = document.forms["myForm"]["fname"].value;if (x == null || x == "") {alert("需要輸入名字。");return false;} }以上 JavaScript 代碼可以通過 HTML 代碼來調用。
HTML 表單實例。示例:嘗試一下?
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script> function validateForm() {var x = document.forms["myForm"]["fname"].value;if (x == null || x == "") {alert("需要輸入名字。");return false;} } </script> </head> <body><form name="myForm" action="demo_form.php" onsubmit="return validateForm()" method="post"> 名字: <input type="text" name="fname"> <input type="submit" value="提交"> </form></body> </html>?
HTML 表單自動驗證
HTML 表單驗證也可以通過瀏覽器來自動完成。
如果表單字段 (fname) 的值為空,?required?屬性會阻止表單提交:
實例
<form action="demo_form.php" method="post"><input type="text" name="fname" required="required"><input type="submit" value="提交"> </form>示例:嘗試一下
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body><form action="demo_form.php" method="post"><input type="text" name="fname" required="required"><input type="submit" value="提交"> </form><p>點擊提交按鈕,如果輸入框是空的,瀏覽器會提示錯誤信息。</p></body> </html>?
數據驗證
數據驗證用于確保用戶輸入的數據是有效的。
典型的數據驗證有:
- 必需字段是否有輸入?
- 用戶是否輸入了合法的數據?
- 在數字字段是否輸入了文本?
大多數情況下,數據驗證用于確保用戶正確輸入數據。
數據驗證可以使用不同方法來定義,并通過多種方式來調用。
服務端數據驗證是在數據提交到服務器上后再驗證。
客戶端數據驗證是在數據發送到服務器前,在瀏覽器上完成驗證。
?
HTML 約束驗證
HTML5 新增了 HTML 表單的驗證方式:約束驗證(constraint validation)。
約束驗證是表單被提交時瀏覽器用來實現驗證的一種算法。
HTML 約束驗證基于:
- HTML 輸入屬性
- CSS 偽類選擇器
- DOM 屬性和方法
約束驗證 HTML 輸入屬性
| disabled | 規定輸入的元素不可用 |
| max | 規定輸入元素的最大值 |
| min | 規定輸入元素的最小值 |
| pattern | 規定輸入元素值的模式 |
| required | 規定輸入元素字段是必需的 |
| type? | 規定輸入元素的類型 |
完整列表,請查看?HTML 輸入屬性。
約束驗證 CSS 偽類選擇器
| :disabled | 選取屬性為 "disabled" 屬性的 input 元素 |
| :invalid | 選取無效的 input 元素 |
| :optional | 選擇沒有"required"屬性的 input 元素 |
| :required | 選擇有"required"屬性的 input 元素 |
| :valid | 選取有效值的 input 元素 |
完整列表,請查看?CSS 偽類。
?
?
JavaScript?表單驗證
?
JavaScript 表單驗證
JavaScript 可用來在數據被送往服務器前對 HTML 表單中的這些輸入數據進行驗證。
表單數據經常需要使用 JavaScript 來驗證其正確性:
- 驗證表單數據是否為空?
- 驗證輸入是否是一個正確的email地址?
- 驗證日期是否輸入正確?
- 驗證表單輸入內容是否為數字型?
?
必填(或必選)項目
下面的函數用來檢查用戶是否已填寫表單中的必填(或必選)項目。假如必填或必選項為空,那么警告框會彈出,并且函數的返回值為 false,否則函數的返回值則為 true(意味著數據沒有問題):
function validateForm() {var x=document.forms["myForm"]["fname"].value;if (x==null || x==""){alert("姓必須填寫");return false;} }以上函數在 form 表單提交時被調用:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <head> <script> function validateForm(){ var x=document.forms["myForm"]["fname"].value; if (x==null || x==""){alert("姓必須填寫");return false;} } </script> </head> <body><form name="myForm" action="demo-form.php" onsubmit="return validateForm()" method="post"> 姓: <input type="text" name="fname"> <input type="submit" value="提交"> </form></body> </html>實例:嘗試一下 ?
?
E-mail 驗證
下面的函數檢查輸入的數據是否符合電子郵件地址的基本語法。
意思就是說,輸入的數據必須包含 @ 符號和點號(.)。同時,@ 不可以是郵件地址的首字符,并且 @ 之后需有至少一個點號:
function validateForm(){var x=document.forms["myForm"]["email"].value;var atpos=x.indexOf("@");var dotpos=x.lastIndexOf(".");if (atpos<1 || dotpos<atpos+2 || dotpos+2>=x.length){alert("不是一個有效的 e-mail 地址");return false;} }下面是連同 HTML 表單的完整代碼:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <head> <script> function validateForm(){var x=document.forms["myForm"]["email"].value;var atpos=x.indexOf("@");var dotpos=x.lastIndexOf(".");if (atpos<1 || dotpos<atpos+2 || dotpos+2>=x.length){alert("不是一個有效的 e-mail 地址");return false;} } </script> </head> <body><form name="myForm" action="demo-form.php" onsubmit="return validateForm();" method="post"> Email: <input type="text" name="email"> <input type="submit" value="提交"> </form></body> </html>示例::嘗試一下
?
?
JavaScript 驗證 API
?
- 約束驗證 DOM 方法
- 約束驗證 DOM 屬性
- Validity 屬性
:https://www.runoob.com/js/js-validation-api.html
?
?
JavaScript?保留關鍵字
?
在 JavaScript 中,一些標識符是保留關鍵字,不能用作變量名或函數名。
:https://www.runoob.com/js/js-reserved.html
?
?
this 關鍵字
?
面向對象語言中 this 表示當前對象的一個引用。
但在 JavaScript 中 this 不是固定不變的,它會隨著執行環境的改變而改變。
- 在方法中,this 表示該方法所屬的對象。
- 如果單獨使用,this 表示全局對象。
- 在函數中,this 表示全局對象。
- 在函數中,在嚴格模式下,this 是未定義的(undefined)。
- 在事件中,this 表示接收事件的元素。
- 類似 call() 和 apply() 方法可以將 this 引用到任何對象。
示例:
var person = {firstName: "John",lastName : "Doe",id : 5566,fullName : function() {return this.firstName + " " + this.lastName;} };console.log(person.fullName());?
方法中的 this
在對象方法中, this 指向調用它所在方法的對象。
在上面一個實例中,this 表示 person 對象。fullName 方法所屬的對象就是 person。
?
單獨使用 this
單獨使用 this,則它指向 全局(Global)對象。
在瀏覽器中,window 就是該全局對象為 [object Window]:
示例:
var x = this;嚴格模式下,如果單獨使用,this 也是指向全局(Global)對象。示例:
"use strict"; var x = this;?
事件中的 this
在 HTML 事件句柄中,this 指向了接收事件的 HTML 元素:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body><h2>JavaScript <b>this</b> 關鍵字</h2><button onclick="this.style.display='none'">點我后我就消失了</button></body> </html>?
對象方法中綁定
下面實例中,this 是 person 對象,person 對象是函數的所有者。示例:
var person = {firstName : "John",lastName : "Doe",id : 5566,myFunction : function() {return this;} };示例:(?說明:?this.firstName?表示?this?(person) 對象的?firstName?屬性。 )
var person = {firstName: "John",lastName : "Doe",id : 5566,fullName : function() {return this.firstName + " " + this.lastName;} };?
顯式函數綁定
在 JavaScript 中函數也是對象,對象則有方法,apply 和 call 就是函數對象的方法。這兩個方法異常強大,他們允許切換函數執行的上下文環境(context),即 this 綁定的對象。
在下面實例中,當我們使用 person2 作為參數來調用 person1.fullName 方法時,?this?將指向 person2, 即便它是 person1 的方法:
var person1 = {fullName: function() {return this.firstName + " " + this.lastName;} } var person2 = {firstName:"John",lastName: "Doe", } person1.fullName.call(person2); // 返回 "John Doe"?
?
JSON
?
JSON 是用于存儲和傳輸數據的格式。JSON 通常用于服務端向網頁傳遞數據 。
?
什么是 JSON?
- JSON 英文全稱?JavaScript?Object?Notation
- JSON 是一種輕量級的數據交換格式。
- JSON是獨立的語言?*
- JSON 易于理解。
JSON 使用 JavaScript 語法,但是 JSON 格式僅僅是一個文本。文本可以被任何編程語言讀取及作為數據格式傳遞。
?
JSON 實例
以下 JSON 語法定義了 sites 對象: 3 條網站信息(對象)的數組:
{"sites":[{"name":"Runoob", "url":"www.runoob.com"}, {"name":"Google", "url":"www.google.com"},{"name":"Taobao", "url":"www.taobao.com"} ]}?
JSON 格式化后為 JavaScript 對象
JSON 格式在語法上與創建 JavaScript 對象代碼是相同的。
由于它們很相似,所以 JavaScript 程序可以很容易的將 JSON 數據轉換為 JavaScript 對象。
?
JSON 語法規則
- 數據為 鍵/值 對。
- 數據由逗號分隔。
- 大括號保存對象
- 方括號保存數組
?
JSON 數據 - 一個名稱對應一個值
JSON 數據格式為 鍵/值 對,就像 JavaScript 對象屬性。
鍵/值對包括字段名稱(在雙引號中),后面一個冒號,然后是值:"name":"Runoob"
?
JSON 對象
JSON 對象保存在大括號內。
就像在 JavaScript 中, 對象可以保存多個 鍵/值 對:{"name":"Runoob", "url":"www.runoob.com"}
?
JSON 數組
JSON 數組保存在中括號內。
就像在 JavaScript 中, 數組可以包含對象:
"sites":[{"name":"Runoob", "url":"www.runoob.com"}, {"name":"Google", "url":"www.google.com"},{"name":"Taobao", "url":"www.taobao.com"} ]在以上實例中,對象 "sites" 是一個數組,包含了三個對象。每個對象為站點的信息(網站名和網站地址)。
?
JSON 字符串轉換為 JavaScript 對象
通常我們從服務器中讀取 JSON 數據,并在網頁中顯示數據。
簡單起見,我們網頁中直接設置 JSON 字符串 (你還可以閱讀我們的?JSON 教程):
首先,創建 JavaScript 字符串,字符串為 JSON 格式的數據:
var text = '{ "sites" : [' + '{ "name":"Runoob" , "url":"www.runoob.com" },' + '{ "name":"Google" , "url":"www.google.com" },' + '{ "name":"Taobao" , "url":"www.taobao.com" } ]}';然后,使用 JavaScript 內置函數 JSON.parse() 將字符串轉換為 JavaScript 對象:var obj = JSON.parse(text);
最后,在你的頁面中使用新的 JavaScript 對象:
var text = '{ "sites" : [' +'{ "name":"Runoob" , "url":"www.runoob.com" },' +'{ "name":"Google" , "url":"www.google.com" },' +'{ "name":"Taobao" , "url":"www.taobao.com" } ]}';obj = JSON.parse(text); document.getElementById("demo").innerHTML = obj.sites[1].name + " " + obj.sites[1].url;?
相關函數
| JSON.parse() | 用于將一個 JSON 字符串轉換為 JavaScript 對象。 |
| JSON.stringify() | 用于將 JavaScript 值轉換為 JSON 字符串。 |
更多 JSON 信息,你可以閱讀我們的?JSON 教程。
?
?
javascript:void(0)?含義
void() 僅僅是代表不返回任何值,但是括號內的表達式還是要運行,如:void(alert("Warnning!"))
我們經常會使用到?javascript:void(0)?這樣的代碼,那么在 JavaScript 中?javascript:void(0)?代表的是什么意思呢?
javascript:void(0)?中最關鍵的是?void?關鍵字,?void?是 JavaScript 中非常重要的關鍵字,該操作符指定要計算一個表達式但是不返回值。
語法格式如下:
void func() javascript:void func()或者
void(func()) javascript:void(func())示例:(? 嘗試一下 )下面的代碼創建了一個超級鏈接,當用戶點擊以后不會發生任何事。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body><a href="javascript:void(0)">單此處什么也不會發生</a></body> </html>當用戶鏈接時,void(0) 計算為 0,但 Javascript 上沒有任何效果。以下實例中,在用戶點擊鏈接后顯示警告信息:(?嘗試一下?)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body><p>點擊以下鏈接查看結果:</p> <a href="javascript:void(alert('Warning!!!'))">點我!</a></body> </html>以下實例中參數 a 將返回 undefined :
function getValue(){var a,b,c;a = void ( b = 5, c = 7 );document.write('a = ' + a + ' b = ' + b +' c = ' + c ); }?
href="#"與href="javascript:void(0)"的區別
- #?包含了一個位置信息,默認的錨是#top?也就是網頁的上端。在頁面很長的時候會使用?#?來定位頁面的具體位置,格式為:# + id。
- 而 javascript:void(0), 僅僅表示一個死鏈接。如果你要定義一個死鏈接請使用 javascript:void(0) 。
示例:(?嘗試一下?)
<a href="javascript:void(0);">點我沒有反應的!</a> <a href="#pos">點我定位到指定位置!</a> <br> ... <br> <p id="pos">尾部定位點</p>?
?
JavaScript 異步編程
?
異步的概念
異步(Asynchronous, async)是與同步(Synchronous, sync)相對的概念。
- 傳統單線程編程中,程序的運行是同步的(同步不意味著所有步驟同時運行,而是指步驟在一個控制流序列中按順序執行)。
- 而異步的概念則是不保證同步的概念,也就是說,一個異步過程的執行將不再與原有的序列有順序關系。
簡單來理解就是:同步按你的代碼順序執行,異步不按照代碼順序執行,異步的執行效率更高。
以上是關于異步的概念的解釋,接下來我們通俗地解釋一下異步:異步就是從主線程發射一個子線程來完成任務。
什么時候用異步編程
在前端編程中(甚至后端有時也是這樣),我們在處理一些簡短、快速的操作時,例如計算 1 + 1 的結果,往往在主線程中就可以完成。主線程作為一個線程,不能夠同時接受多方面的請求。所以,當一個事件沒有結束時,界面將無法處理其他請求。
現在有一個按鈕,如果我們設置它的 onclick 事件為一個死循環,那么當這個按鈕按下,整個網頁將失去響應。
為了避免這種情況的發生,我們常常用子線程來完成一些可能消耗時間足夠長以至于被用戶察覺的事情,比如讀取一個大文件或者發出一個網絡請求。因為子線程獨立于主線程,所以即使出現阻塞也不會影響主線程的運行。但是子線程有一個局限:一旦發射了以后就會與主線程失去同步,我們無法確定它的結束,如果結束之后需要處理一些事情,比如處理來自服務器的信息,我們是無法將它合并到主線程中去的。
為了解決這個問題,JavaScript 中的異步操作函數往往通過回調函數來實現異步任務的結果處理。
?
回調函數
回調函數就是一個函數,它是在我們啟動一個異步任務的時候就告訴它:等你完成了這個任務之后要干什么。這樣一來主線程幾乎不用關心異步任務的狀態了,他自己會善始善終。
示例:
function print() {console.log('test callback') } setTimeout(print, 3000); console.log('main thread continue')這段程序中的 setTimeout 就是一個消耗時間較長(3 秒)的過程,它的第一個參數是個回調函數,第二個參數是毫秒數,這個函數執行之后會產生一個子線程,子線程會等待 3 秒,然后執行回調函數 "print",在命令行輸出 "Time out"。當然,JavaScript 語法十分友好,我們不必單獨定義一個函數 print ,我們常常將上面的程序寫成:
注意:?setTimeout 會在子線程中等待 3 秒,在 setTimeout 函數執行之后主線程并沒有停止。。。
function print() {} setTimeout(print, 3000); console.log('main thread continue')setTimeout(function () {console.log('test callback'); }, 3000);?
異步 AJAX
除了 setTimeout 函數以外,異步回調廣泛應用于 AJAX 編程。有關于 AJAX 詳細請參見:https://www.runoob.com/ajax/ajax-tutorial.html
XMLHttpRequest 常常用于請求來自遠程服務器上的 XML 或 JSON 數據。一個標準的 XMLHttpRequest 對象往往包含多個回調:
示例:(?嘗試一下?)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body><p><strong>以下內容是通過異步請求獲取的:</strong></p> <p id="demo"></p> <script> var xhr = new XMLHttpRequest();xhr.onload = function () {// 輸出接收到的文字數據document.getElementById("demo").innerHTML=xhr.responseText; }xhr.onerror = function () {document.getElementById("demo").innerHTML="請求出錯"; }// 發送異步 GET 請求 xhr.open("GET", "https://www.runoob.com/try/ajax/ajax_info.txt", true); xhr.send(); </script></body> </html>XMLHttpRequest 的 onload 和 onerror 屬性都是函數,分別在它請求成功和請求失敗時被調用。
如果你使用完整的 jQuery 庫,也可以更加優雅的使用異步 AJAX:
示例:(?嘗試一下?)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"> </script> <script> $(document).ready(function(){$("button").click(function(){$.get("/try/ajax/demo_test.php",function(data,status){alert("數據: " + data + "\n狀態: " + status);});}); }); </script> </head> <body><button>發送一個 HTTP GET 請求并獲取返回結果</button></body> </html>?
?
JavaScript 的 Promise
?
在學習本章節內容前,你需要先了解什么是異步編程,可以參考:JavaScript 異步編程
Promise 是一個 ECMAScript 6 提供的類,目的是更加優雅地書寫復雜的異步任務。
由于 Promise 是 ES6 新增加的,所以一些舊的瀏覽器并不支持,蘋果的 Safari 10 和 Windows 的 Edge 14 版本以上瀏覽器才開始支持 ES6 特性。
?
構造 Promise
現在我們新建一個 Promise 對象:
new Promise(function (resolve, reject) {// 要做的事情... });通過新建一個 Promise 對象好像并沒有看出它怎樣 "更加優雅地書寫復雜的異步任務"。我們之前遇到的異步任務都是一次異步,如果需要多次調用異步函數呢?例如,如果我想分三次輸出字符串,第一次間隔 1 秒,第二次間隔 4 秒,第三次間隔 3 秒。示例:
setTimeout(function () {console.log("First");setTimeout(function () {console.log("Second");setTimeout(function () {console.log("Third");}, 3000);}, 4000); }, 1000);這段程序實現了這個功能,但是它是用 "函數瀑布" 來實現的。可想而知,在一個復雜的程序當中,用 "函數瀑布" 實現的程序無論是維護還是異常處理都是一件特別繁瑣的事情,而且會讓縮進格式變得非常冗贅。
現在我們用 Promise 來實現同樣的功能。示例:
new Promise(function (resolve, reject) {setTimeout(function () {console.log("First");resolve();}, 1000); }).then(function () {return new Promise(function (resolve, reject) {setTimeout(function () {console.log("Second");resolve();}, 4000);}); }).then(function () {setTimeout(function () {console.log("Third");}, 3000); });這段代碼較長,所以還不需要完全理解它,我想引起注意的是 Promise 將嵌套格式的代碼變成了順序格式的代碼。
?
Promise 的使用
下面我們通過剖析這段 Promise "計時器" 代碼來講述 Promise 的使用:
Promise 構造函數只有一個參數,是一個函數,這個函數在構造之后會直接被異步運行,所以我們稱之為起始函數。起始函數包含兩個參數 resolve 和 reject。
當 Promise 被構造時,起始函數會被異步執行。示例:
new Promise(function (resolve, reject) {console.log("Run"); });這段程序會直接輸出?Run。
resolve 和 reject 都是函數,其中調用 resolve 代表一切正常,reject 是出現異常時所調用的。示例:
new Promise(function (resolve, reject) {var a = 0;var b = 1;if (b == 0) reject("Diveide zero");else resolve(a / b); }).then(function (value) {console.log("a / b = " + value); }).catch(function (err) {console.log(err); }).finally(function () {console.log("End"); });這段程序執行結果是:
a / b = 0 EndPromise 類有 .then() .catch() 和 .finally() 三個方法,這三個方法的參數都是一個函數,.then() 可以將參數中的函數添加到當前 Promise 的正常執行序列,.catch() 則是設定 Promise 的異常處理序列,.finally() 是在 Promise 執行的最后一定會執行的序列。 .then() 傳入的函數會按順序依次執行,有任何異常都會直接跳到 catch 序列:
示例:
new Promise(function (resolve, reject) {console.log(1111);resolve(2222); }).then(function (value) {console.log(value);return 3333; }).then(function (value) {console.log(value);throw "An error"; }).catch(function (err) {console.log(err); });執行結果:
1111 2222 3333 An errorresolve() 中可以放置一個參數用于向下一個 then 傳遞一個值,then 中的函數也可以返回一個值傳遞給 then。但是,如果 then 中返回的是一個 Promise 對象,那么下一個 then 將相當于對這個返回的 Promise 進行操作,這一點從剛才的計時器的例子中可以看出來。
reject() 參數中一般會傳遞一個異常給之后的 catch 函數用于處理異常。
但是請注意以下兩點:
- resolve 和 reject 的作用域只有起始函數,不包括 then 以及其他序列;
- resolve 和 reject 并不能夠使起始函數停止運行,別忘了 return。
?
Promise 函數
上述的 "計時器" 程序看上去比函數瀑布還要長,所以我們可以將它的核心部分寫成一個 Promise 函數:
function print(delay, message) {return new Promise(function (resolve, reject) {setTimeout(function () {console.log(message);resolve();}, delay);}); }然后我們就可以放心大膽的實現程序功能了:
print(1000, "First").then(function () {return print(4000, "Second"); }).then(function () {print(3000, "Third"); });這種返回值為一個 Promise 對象的函數稱作 Promise 函數,它常常用于開發基于異步操作的庫。
?
回答常見的問題(FAQ)
Q: then、catch 和 finally 序列能否順序顛倒?
A: 可以,效果完全一樣。但不建議這樣做,最好按 then-catch-finally 的順序編寫程序。
Q: 除了 then 塊以外,其它兩種塊能否多次使用?
A: 可以,finally 與 then 一樣會按順序執行,但是 catch 塊只會執行第一個,除非 catch 塊里有異常。所以最好只安排一個 catch 和 finally 塊。
Q: then 塊如何中斷?
A: then 塊默認會向下順序執行,return 是不能中斷的,可以通過 throw 來跳轉至 catch 實現中斷。
Q: 什么時候適合用 Promise 而不是傳統回調函數?
A: 當需要多次順序執行異步操作的時候,例如,如果想通過異步方法先后檢測用戶名和密碼,需要先異步檢測用戶名,然后再異步檢測密碼的情況下就很適合 Promise。
Q: Promise 是一種將異步轉換為同步的方法嗎?
A: 完全不是。Promise 只不過是一種更良好的編程風格。
Q: 什么時候我們需要再寫一個 then 而不是在當前的 then 接著編程?
A: 當你又需要調用一個異步任務的時候。
?
異步函數
異步函數(async function)是 ECMAScript 2017 (ECMA-262) 標準的規范,幾乎被所有瀏覽器所支持,除了 Internet Explorer。
在 Promise 中我們編寫過一個 Promise 函數:
function print(delay, message) {return new Promise(function (resolve, reject) {setTimeout(function () {console.log(message);resolve();}, delay);}); }然后用不同的時間間隔輸出了三行文本:
print(1000, "First").then(function () {return print(4000, "Second"); }).then(function () {print(3000, "Third"); });我們可以將這段代碼變得更好看:
async function asyncFunc() {await print(1000, "First");await print(4000, "Second");await print(3000, "Third"); } asyncFunc();哈!這豈不是將異步操作變得像同步操作一樣容易了嗎!
這次的回答是肯定的,異步函數 async function 中可以使用 await 指令,await 指令后必須跟著一個 Promise,異步函數會在這個 Promise 運行中暫停,直到其運行結束再繼續運行。
異步函數實際上原理與 Promise 原生 API 的機制是一模一樣的,只不過更便于程序員閱讀。
處理異常的機制將用 try-catch 塊實現:
async function asyncFunc() {try {await new Promise(function (resolve, reject) {throw "Some error"; // 或者 reject("Some error")});} catch (err) {console.log(err);// 會輸出 Some error} } asyncFunc();如果 Promise 有一個正常的返回值,await 語句也會返回它:
async function asyncFunc() {let value = await new Promise(function (resolve, reject) {resolve("Return value");});console.log(value); } asyncFunc();程序會輸出:Return value
更多內容:JavaScript Promise 對象
?
?
?
?
總結
以上是生活随笔為你收集整理的菜鸟教程 之 JavaScript 教程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 爬虫框架 - PySpid
- 下一篇: Auto.JS 开发