為一個使用了jQuery很多年 的人,最近,我成為了一個Vue的皈依者,我認為從一個框架到另一個框架的遷移過程將是一個值得討論的有趣的話題。
在我開始之前,我想清楚地說明一點。我并沒有以任何方式告訴任何人去停止使用jQuery。jQuery最近相當流行,而且見鬼,我幾年前也寫過類似的東西(“我如何(不)使用jQuery”)。如果你使用jQuery完成了你的項目,并且你的最終用戶成功地使用了你的站點,那么你將獲得更多的動力去繼續使用對你有用的東西。
本指南更適合那些可能具有多年jQuery經驗并希望了解如何使用Vue來完成工作的人。考慮到這一點,我將重點介紹我所認為的“核心”jQuery用例。我不會涵蓋每一個可能的特性,而是用“我經常使用jQuery來完成 [X]”的方式來代替,這種方式可能更適合那些考慮學習Vue的人。(順便提一句,請注意,我編寫示例的方式只是執行一個任務的一種方式。jQuery和Vue都提供了多種方法來實現相同的目標,這是一件很棒的事情!)
記住了這一點,我們來思考一些可以使用jQuery完成的高級的東西:
當然,jQuery還有更多的功能,但是這些用途(至少在我看來)涵蓋了最常見的用例。還要注意,在上面的列表中有很多異花授粉現象。那么,我們應該從簡單的一一對應的比較開始嗎?不,沒那么快。我們先從介紹Vue應用程序中的主要差異開始。
#定義Vue的使用場景
當我們將jQuery加入到頁面上時,我們基本上是在JavaScript代碼中添加一把瑞士軍刀來處理常見的web開發任務。我們可以按照我們認為合適的順序來處理任何一個用例。例如,今天客戶可能會要求表單驗證,然后在一個月左右后,又要求在站點的頭部添加一個基于Ajax的搜索表單。
Vue在這方面有一個顯著的不同。當使用Vue開始一個項目時,我們首先會在DOM中定義一個我們希望Vue專用的“區域”。因此,我們來考慮一個簡單的原型web頁面:
在一個典型的jQuery應用程序中,我們可以編寫代碼來處理頭部、側邊欄和登錄表單等。這很簡單:
而在一個Vue應用程序中,我們首先需要指定要處理的內容。假設我們的客戶首先要求我們向loginForm元素添加驗證,那么我們的Vue代碼就要指定這一點:
這意味著,如果客戶后來決定讓我們在側邊欄中添加一些內容,那我們通常會添加第二個Vue應用程序:
這是件壞事嗎?絕對不是。我們馬上就會得到封裝的好處。如果我們不小心使用了一個具有泛型名稱的變量(我們都這樣做過),我們不必擔心它與代碼的其他部分發生沖突。過后,當客戶端增加了另一個要求時,像這樣將我們獨特的、邏輯化的Vue代碼集區分開就會確保每一個Vue應用程序不會相互干擾。
所以,是的,這是一件好事。但當我第一次開始使用Vue時,它絕對讓我停了下來。現在,進入我們的用例。
#在DOM中查找東西
你會發現另一個有趣或可怕的方面是如何“在DOM中查找東西”。這有點模糊,但我們來考慮一個強有力的例子。我們有一個按鈕,當它被點擊時,我們讓一些事情發生。下面是一個簡短的例子,展示了它是怎樣的:
現在我們來將這個例子與用Vue的實現方式進行比較:
這個Vue應用程序有點冗長,但是請注意標記是如何在操作(“click”)和將要調用的函數之間建立一個直接連接的。Vue的代碼并沒有與DOM進行向后綁定(我們在el部分之外定義了它需要運行的地方)。這是Vue最吸引我的地方之一——它能很容易地告訴你將要發生什么。此外,我不需要過多地擔心ID值和選擇器。如果我更改了按鈕的類或ID,我不需要返回代碼中去更新選擇器。
我們來考慮另一個例子:在DOM中查找和更改文本。想象一下那個按鈕,單擊它,現在會更改DOM的另一部分的文本。
我已經添加了一個新的span,現在,當按鈕被單擊時,我們使用另一個選擇器來查找它,并使用一個jQuery工具方法來更改其中的文本。現在我們來考慮一下Vue版本:
在本例中,我們使用Vue的模板語言(突出顯示的行)來指定我們希望在span中呈現的一個變量,在本例中是resultText。現在,當按鈕被單擊時,我們更改該值,span的內部文本將會自動更改。
順便說一句,Vue支持v-on屬性的簡寫,因此示例中的按鈕可以用@click=“ doSomething"代替。
#讀寫表單變量
處理表單可能是我們可以用JavaScript做的最常見也是最有用的事情之一。甚至在JavaScript之前,我早期的“web開發”大部分都是通過編寫Perl腳本來處理表單提交。作為接受用戶輸入的主要方式,表單對web來說一直都是很重要的,而且很可能會在相當長一段時間內保持不變。我們來考慮一個簡單的jQuery例子,它將讀取幾個表單字段并設置另一個:
這段代碼演示了jQuery如何通過val( )方法讀寫表單。最后,我們從DOM中獲取四個項目(所有的三個表單字段和一個按鈕),并使用簡單的數學方法來生成一個結果。現在我們來考慮一下Vue版本:
這里介紹了一些有趣的Vue快捷方法。首先,v-model是Vue如何在DOM和JavaScript中的值之間創建雙向數據綁定。data塊變量將自動與表單字段同步。更改數據,表單就會更新。更改表單,數據就會更新。.number是Vue的一個標志,用于將表單字段的繼承字符串值視為數字。如果我們不做這一步,按原樣做加法,我們會看到字符串加法,而不是算術。我已經使用JavaScript處理了將近一個世紀了,但還是搞砸了。
另一個簡單的“技巧”是@click.prevent。首先,@click為按鈕定義了一個單擊處理程序,然后.prevent部分會阻止瀏覽器提交表單的默認行為(相當于event.preventDefault( ))。
最后一個是綁定到該按鈕的doSum方法進行的相加操作。注意,它只處理數據變量(Vue在this作用域內允許對這些變量進行操作)。
雖然這主要是我個人的感覺,但我非常喜歡在用Vue編寫腳本時,腳本中沒有查詢選擇器,以及HTML如何更清楚地顯示它在做什么。
最后,我們甚至可以完全去掉按鈕:
Vue的一個更酷的特性是computed properties(計算屬性)。它們是虛擬值,可以識別其派生值何時被更新。在上面的代碼中,只要兩個表單字段中的任何一個發生更改,總和就會更新。這也適用于表單字段之外。我們可以這樣渲染其總和:
#使用Ajax
值得稱贊的是,jQuery使Ajax的使用變得非常簡單。事實上,我可以說我已經以一種“普通”的方式完成了Ajax,可能總共只有一次(如果你對此很好奇,你可以查看XMLHttpRequest規范,并且你可能會為你已經避免了它而感到高興)。jQuery簡單的$.get(…)方法在很多情況下都能工作,并且當它需要在更復雜的東西中使用時,$.ajax()也能使它變得簡單。jQuery做得很好的另一件事是它處理JSONP請求的方式。雖然現在使用CORS基本上沒有必要,但JSONP是一種處理向不同域中的API發出請求的方法。
那么,Vue如何讓Ajax變得更簡單呢?沒有什么!
好吧,聽起來很嚇人,但其實并不可怕。有許多處理HTTP請求的選項,而Vue.js采用了一種更不可知的方式,讓我們開發人員決定如何處理它。所以,是的,這確實意味著更多的工作,但我們有一些不錯的選擇。
首先應該考慮的是Axios,這是一個Promise-based庫,在Vue社區中非常流行。下面是一個使用它的簡單的例子(摘自它們的README文件):
Axios支持POST請求,當然,它也允許我們在許多其他選項中指定頭文件。
雖然Axios在Vue開發人員中非常流行,但我并不是真心喜歡它。(至少現在還沒有。)相反,我更喜歡Fetch。Fetch不是一個外部庫,而是執行HTTP請求的一種web標準方法。Fetch在大約90%的瀏覽器
上都有很好的支持,雖然這意味著使用它并不完全安全,但是我們總是可以使用一個我們需要的polyfill。
雖然這完全超出了我們在這里討論的范圍,但是Kingsley Silas寫了一本關于在React中使用Axios和Fetch的優秀指南。
和Axios一樣,Fetch也是Promise-based的,并且有一個友好的API:
Axios和Fetch都涵蓋了所有類型的HTTP請求,所以它們都能滿足任意數量的需求。讓我們看一個簡單的比較。下面是一個使用了星球大戰API的簡單jQuery演示。
在上面的示例中,我使用$.get調用該API并返回一個電影列表。然后我用這些數據生成一個標題列表作為 li 標記元素,并將其全部插入到一個ul塊中。
現在,讓我們考慮一個使用Vue的例子:
其中最好的部分可能是使用v-for模板。注意Vue是如何做到與布局無關的(至少與JavaScript無關)。數據是從該API中獲取的。它被分配了一個變量。布局處理如何顯示它。我一直討厭在我的JavaScript中使用HTML,但是jQuery提供了解決方案,把它嵌入到Vue中看起來就很自然很合適。
#一個完整的(在某種程度上有點瑣碎)例子
為了更好地理解它,讓我們考慮一個更真實的例子。我們的客戶要求我們為一個產品API構建一個支持Ajax的前端搜索接口。功能列表包括:
我們從jQuery版本開始。首先, HTML部分如下:
有一個帶有兩個過濾器和兩個div的表單。一個用做搜索或報告錯誤時的臨時狀態,另一個用于呈現結果。現在,檢查代碼。
代碼首先為要處理的每個DOM項(表單字段、按鈕和div)創建一組變量。代碼的邏輯核心在按鈕的點擊處理程序中。我們進行驗證,如果一切正常,就對該API執行一個POST請求。當請求返回時,我們要么呈現結果
,要么在沒有匹配的情況下顯示消息。
你可以使用下面的CodePen來運行這個演示的完整版本。
現在讓我們考慮Vue版本。同樣,我們先從布局開始:
從頂部看,其中的變化包括:
現在讓我們看看代碼。
值得調用的第一個塊是data字段集。有些映射到表單字段,有些映射到結果、狀態消息等等。searchProducts方法處理的內容與jQuery版本大致相同,但通常直接綁定到DOM的代碼要少得多。例如,即使我們知道結果是以一個無序列表列出的,但代碼本身并不關心這一點。它只是進行賦值,標記才處理呈現值。總的來說,與jQuery代碼相比,JavaScript代碼更關心邏輯,jQuery代碼“感覺”是更好的分離了關注點。
和以前一樣,這里有一個CodePen可以讓你自己試試:
#jQuery將死! Vue萬歲!
好吧,這有點過分了。正如我在開始時所說的,如果你喜歡使用jQuery并且它對你有用的話,那我覺得你完全沒必要更改任何東西。
不過,我想說的是,對于習慣使用jQuery的人來說,Vue似乎是一個很好的“下一步”。Vue支持復雜的應用程序,并為搭建和構建項目提供了一個非常棒的命令行工具。但是對于更簡單的任務來說,Vue是一個很棒的“現代jQuery”的替代品,它已經成為我開發的可選工具!
有關使用Vue替代jQuery的另一個觀點,請查看Sarah Drasner的“使用Vue.js替換jQuery:無需構建步驟”,因為它包含了其他一些超級有用的例子。
英文原文:https://css-tricks.com/making-the-move-from-jquery-to-vue/
譯者:浣熊君( ????? )
要說 js 的深淺拷貝,就不得不提 js 的兩大數據類型:基本數據類型和引用類型。基本數據類型的變量名和值都存儲在棧中,對于引用類型的變量名存儲在棧中,而值存儲在堆中。由于存儲方式不同,所以導致了他們復制的時候方式不同。
淺拷貝是創建一個新對象,這個對象有著原始對象屬性值的一份精準拷貝。如果屬性是基本類型,拷貝的就是基本類型的值,如果是引用類型,拷貝的就是內存地址,所以如果其中一個對象改變了這個地址,就會影響到另外一個對象。
深拷貝是將一個對象從內存中完整的拷貝一份出來,從內存堆中存放一個新的對象。這是兩個對象,所以修改其中一個,另外一個不會受影響。
深淺拷貝主要針對的是引用類型,簡單數據類型不受影響。
相關筆試題
var person={
name:"前端人",
hobby:['學習','敲代碼','潛水']
}
function copy(source){
var newObj=new Object()
for(var i in source){
if(source.hasOwnProperty(i)){
newObj[i]=source[i]
}
}
return newObj
}
var p1=copy(person);
p1.name="Web Person"
console.log(person.name)
console.log(p1.name)
p1.hobby=["內卷"]
console.info(person.hobby)
console.info(p1.hobby)
/*運行結果:
前端人
Web Person
["學習", "敲代碼", "潛水"]
["內卷"]
*/
js 數據類型一共有 8 種,分為兩大類:基本類型和引用類型。
它們的數據類型分別為:
基本類型:string、number、boolean、null、undefined、symbol、bigint
引用類型:object
相關面試題
// 注意:其他類型與數值進行相加時,其他類型的轉為 number 類型
console.log( true+1 ) // 2
console.log( undefined +1 ) // NaN
console.log( null ) //object
console.log( undefined ) // undefined
共有 6 種方式,分別為:
它們的區別介紹:
1、async:為 <script>標簽定義了 async 屬性。async 和 html 解析是同步的,不是順次執行 js 腳本,誰先加載完成先執行誰。
<script async type="text/javascript" src="demo1.js" ></script>
<script async type="text/javascript" src="demo2.js" ></script>
2、defer 會等到 html 解析完成之后再執行 js 代碼,如果有多個腳本時,會按照順序依次執行腳本。
<script defer type="text/javascript" src="demo1.js" ></script>
3、js 最后加載
把 js 外部引入的文件放置在頁面的底部,讓 js 最后加載,從而加快頁面加載速度。
4、利用 setTimeout
5、動態創建 DOM 的方式
var element=document.createElement("script");
element.src="box.js";
document.body.appendChild(element);
這種方式通過操作動態加載 js 文件,不觸發的時候不加載,減少頁面文件大小,加快加載速度。
6、使用 jQuery 的 getScript 方法
$.getScript( "box.js",function(){//回調函數,成功獲取文件后執行的函數
console.log("腳本加載完成")
});
相關面試題:
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript" src="box.js"></script>
</head>
<body>
<div id="box"></div>
</body>
</html>
//box.js 代碼如下
console.log( document.getElementById('box') ) // null
box.js 想正常獲取元素 box ,并進行一系列操作應該如何延遲加載 js 文件呢?
作用域通俗地講,就是指一個變量的作用范圍。分為全局作用域和函數作用域。
全局作用域
函數作用域(局部)
函數在被調用的時候會先進行預編譯:
全局作用域預編譯:
函數作用域預編譯:
相關面試題:
<script type="text/javascript">
function fn(a,c){
console.log(a)
var a=12
console.log(a)
console.log(c)
function a(){ }
if(false){
var d=34
}
console.log(d)
console.log(b)
var b=function(){}
console.log(b)
function c(){}
console.log(c)
}
fn(1,2)
</script>
// 運行結果:
/*
function a(){}
12
function c(){}
undefined
undefined
function (){}
function c(){}
*/
null 和 undefined 兩個都表示無的值。
作者設計 js 的時候,借鑒的 java 語言先設計的 null 。null 使用的時候會被隱式轉化成 0,不容易發現錯誤。
console.log( number(null) ) //0
undefined 是為了填補 null 的坑。所以后來又新增了 undefined 。
console.log( number(undefined) ) //NaN
實現 new 操作符的方法:
function create( fn,...args ){
var obj={}
Object.setPrototypeOf( obj,fn.prototype )
var resault=fn.apply(obj,args)
return (resault instanceof Object) ? result : obj
}
7.1、什么是閉包?
閉包就是函數嵌套函數,通過函數內的函數訪問變量的規則,實現外部訪問函數內的變量。
7.2、閉包的特點:
實例3:閉包解決問題
var liArr=document.getElementsByTagName('li')
for(var i=0;i<liArr.length;i++){
(function(i){
liArr[i].onclick=function(){
console.log('點擊元素',liArr[i])
}
})(i)
}
7.3、閉包優點:
防抖和節流就是閉包的經典應用。
7.4、閉包缺點:
8.1、什么是防抖函數?
當持續觸發事件,一定時間內沒有再觸發事件,事件處理函數才會執行一次,如果在設定的時間到來之前又觸發了事件,就會重新計時。
防抖函數常見的實際應用:使用 echart 的時候,瀏覽器 resize 時,需要重新繪制圖表大小,還有典型的輸入框搜索應用。
8.2、節流函數是什么?
當持續觸發事件的時候,保證一段時間內只調用一次事件處理函數,一段時間內,只允許做一件事情。
防抖和節流主要是用來限制觸發頻率較高的事件,再不影響效果的前提條件下,降低事件觸發頻率,減小瀏覽器或服務器的壓力,提升用戶體驗效果。
方法1: new set()
return Array.from(new Set(arr))
// 或
return [...new Set(arr)]
方法2:使用兩次循環
for(var i=0,len=arr.length;i<len;i++){
for(var j=i+1,len=arr.length;j<len;j++){
if( arr[i]===arr[j] ){
arr.splice(i,1)
j--;
len--
}
}
}
return arr
方法3:indexOf 實現
let arr1=[]
for(var i=0;i<arr.length;i++){
if( arr1.indexOf(arr[i])===-1 ){
arr1.push(arr[i])
}
}
return arr1
方法4:includes 實現
let arr1=[]
for(var i=0;i<arr.length;i++){
if( !arr1.includes(arr[i]) ){
arr1.push(arr[i])
}
}
return arr1
方法5:filter 實現
array.indexOf(item,start) start 表示開始檢索的位置。
return arr.filter(( item, index )=>{
return arr.indexOf( item, 0 )==index
})
三者都是改變函數執行的上下文,即改變 this 指向。
它們之間的區別為:
使用場景:
1、需要改變某個函數的this指向時
2、當參數較少時可以使用call,參數較多可以使用apply以數組的方式傳遞
3、當需要重復調用時,可以使用bind新定義一個方法
方法1:isArray
var arr=[1,2,3]
console.log(Array.isArray(arr))
方法2:instanceof
var arr=[1,2,3]
console.log( arr instanceof Array )
console.log( arr instanceof Object )
該方法不夠嚴謹。
方法3:prototype
console.log( Object.prototype.toString.call(arr).indexOf('Array')>-1 )
方法4:isPrototypeOf
console.log( Array.prototype.isPrototypeOf( arr ) )
方法5:constructor
console.log(arr.constructor.toString().indexOf('Array')>-1 )
slice 是用來截取字符串的,返回一個新數組,但不會影響原數組。
使用語法:
arr.slice( start , end )
截取 arr 數組,從 start 開始到 end 結束,第二個參數是可選參數,沒有時從 start 開始截取到結尾。
如果 start 參數是負數時,就會從 arr.lengtn + start 開始截取到結束。
var arr=['a','b','c','d','e']
console.log( arr.slice(-3) ) // ["c", "d", "e"]
console.log(arr) //["a", "b", "c", "d", "e"]
splice 是一個更強大的方法,可以添加、刪除、替換數組元素,返回的是被刪除元素,它的操作會改變原數組。
使用語法:
splice( start, n, new )
從 start 開始,刪除 n 個元素,然后把 new 添加到 start 元素之后。第三個參數為可選參數
var arr=['a','b','c','d','e']
var ar=arr.splice( 1, 1 ,'f','g')
console.log('ar',ar) // ["b"]
console.log('arr',arr) // ["a", "f", "g", "c", "d", "e"]
==比較的是值,===除了比較值,還比較類型。
console.log( [1,2]=='1,2' ) // true
console.log( [1,2]==='1,2' ) //false
valueOf 方法返回 Math 對象的原始值,通常由 javascript 在后臺自動調用,并不顯示的出現在代碼中。
console.log([1,2].valueOf()) //[1,2]
console.log('1,2'.valueOf()) //[1,2]
// 所以
console.log( [1,2]=='1,2' ) // true
不管是字符串和數字比較,還是布爾值和數字比較,都會使用 valueOf 隱式轉換。
總結:==需要使用 valueOf() 進行隱式轉換,所以性能差。===會避開一些不必要的麻煩。
大廠筆試題:
var name='window name'
var p1={
name:'p1 name',
showName:function(){
console.info(this.name)
}
}
var fn=p1.showName
fn()
p1.showName()
var p2={
name:'p2 name',
showName:function(fun){
fun()
}
}
p2.showName(p1.showName)
p2.showName=p1.showName
p2.showName()
/*
運行結果:
window name
p1 name
window name
p2 name
*/
這是一道關于 this 指向的面試題,接下來我們就說說 this 是如何指向的?
this 對象是運行時基于函數的執行環境綁定的:
第 1 種:原型鏈繼承
function Parent(){
this.name="前端人"
}
Parent.prototype.showName=function(){
console.log(this.name)
}
function Child(){}
//原型鏈繼承
Child.prototype=new Parent()
var p=new Child()
console.dir(p.name) //前端人
特點:
第 2 種:借用構造函數
function Animal (name) {
this.name=name || 'Animal';
this.sleep=function(){
console.log(this.name + '正在睡覺!');
}
}
Animal.prototype.eat=function(food) {
console.log(this.name + '正在吃:' + food);
};
function Cat(name){
Animal.call(this);
this.name=name || 'Tom';
}
// Test Code
var cat=new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
特點:
還有組合式繼承、ES6 的繼承 和 寄生組合繼承等等。每種繼承方式都有各自的特點和缺點。
JavaScript 語言是一門弱類型語言,存在許多類型錯誤,因此 ES6 引入了嚴格模式概念。
如果不加 ‘use strict’ 常規模式下就是屬于非嚴格模式。
嚴格模式
在 js 文件頂部添加 ‘use strict’ 就屬于嚴格模式,嚴格模式也可以指定在函數內部。
<script>
'use strict'
//或者函數內部
(function(){
'use strict'
})()
</script>
嚴格模式,是為 js 定義來了一種不同的解析與執行模型,在嚴格模式下,ECMAScipt 3 中一些不解和不確定的行為將得到處理,而且會對不安全的操作會拋出異常。‘use strict’ 會告訴瀏覽器引擎可以切換到嚴格模式執行。
嚴格模式與非嚴格模式區別
嚴格模式 | 非嚴格模式 |
變量必須聲明才能賦值 | 變量不進行聲明,可直接賦值 |
不能使用 delete 字符刪除變量或對象 | 可以使用 delete 刪除 |
函數參數變量名不允許重復 | 變量名重復,獲取最后最后那個值 |
普通函數內的 this 為 undefined | 普通函數內的 this 為 window |
不允許使用八進制 | 允許任意進制 |
eval 和 arguments 當做關鍵字,不能被賦值和用作變量名 | 可以使用 eval 、arguments 作為變量名 |
call、apply 傳入 null undefined 保持原樣不被轉為window | 默認轉為 window 對象 |
限制對調用棧的檢測能力,訪問 arguments.callee 會拋出異常 | arguments.callee 運行正常 |
console.log( '2'>10 ) //false
console.log( '2'>'10' ) //true
console.log( 'abc'>'b' ) //false
console.log( 'abc'>'aab' ) //true
console.log( undefined==null ) //true
console.log( NaN==NaN )//false
console.log( []==0 ) //true
console.log( ![]==0 ) //true
console.log( []==[] ) //false
console.log( {}=={} ) //false
console.log( {}==!{} ) //false
阿里面試題1:
<script type="text/javascript">
var p=new Promise(resolve=>{
console.log(4)
resolve(5)
})
function f1(){
console.log(1)
}
function f2(){
setTimeout(()=>{
console.log(2)
},0)
f1()
console.log(3)
p.then(res=>{
console.log(res)
})
}
f2()
</script>
// 運行結果 4 1 3 5 2
// 如果已經了解事件運行機制,就可以跳過該問題了
事件循環機制,event-loop 。包含三部分:調用棧、消息隊列、微任務隊列。
事件循環開始的時候,會從全局一行一行的執行代碼,遇到函數調用的時候,就會壓入調用棧中,當函數執行完成之后,彈出調用棧。
// 如:代碼會一行一行執行,函數全部調用完成之后清空調用棧
function f1(){
console.log(1)
}
function f2(){
f1()
console.log(2)
}
f2()
// 執行結果 1 2
如果遇到 fetch、setInterval、setTimeout 異步操作時,函數調用壓入調用棧時,異步執行內容會被加入消息隊列中,消息隊列中的內容會等到調用棧清空之后才會執行。
// 如:
function f1(){
console.log(1)
}
function f2(){
setTimeout(()=>{
console.log(2)
},0)
f1()
console.log(3)
}
f2()
// 執行結果 :1 3 2
遇到 promise、async、await 異步操作時,執行內容會被加入微任務隊列中,會在調用棧清空之后立即執行。
調用棧加入的微任務隊列會立即執行。
如
let p=new Promise(resolve=>{
console.log('立即執行')
resolve(1) //在 then 調用中執行
})
微任務隊列中內容優先執行,所以比消息隊列中的內容執行得早。
了解這些知識后,再試一下最前面的那道面試題,應該就沒什么問題了。
這個問題就留給讀到最后,能夠堅持學習的人,問問我們自己有什么是我們擅長的?在哪塊領域是我們占據競爭優勢的?
什么是jquery
jQuery是JavaScript的一個庫,jQuery 極大地簡化了 JavaScript 編程。我們在做網站或web應用的過程中,需要用JavaScript為我們完成一些用戶與頁面的交互效果,jQuery庫可以讓我們用更少的JavaScript代碼完成更多的功能。
jQuery的優勢與劣勢
幾年前的web開發,瀏覽器兼容是一個非常重要的問題,前端工程師為了讓自己的程序在多個瀏覽器中正確運行,常常需要編寫更多的代碼來解決瀏覽器兼容問題,jQuery出現之后,它為前端工程師們解決了大量的JavaScript兼容問題,并且封裝了大量的DOM接口和動畫效果,讓我們可以用更少的代碼實現更多的功能并且保持良好的兼容性,jQuery因此迅速成為了世界上最流行的JavaScript庫。
jQuery的流行還有一個原因就是因為它簡單、易上手。很多人在不熟悉JavaScript的情況下,仍然可以使用jQuery完成各種頁面效果。
隨著時間的推移,瀏覽器的兼容問題越來越少,css3也解決了大量的頁面動畫效果,jQuery的優勢漸漸沒有那么突出了,但是它仍然是當前被使用了最多的JavaScript庫,是前端工程師必須掌握的技能。
引入jQuery
要使用jQuery,首先我們需要下載和引入jQuery,我們可以到jquery官網下載jQuery文件,然后在html頁面中添加script標簽引入jQuery。
我們將jQuery放在一個名為script的目錄中,然后用下面的代碼引入jQuery。
1 <body>
2 <script src="script/jquery.js"></script>
3 <script>
4 //這里可以編寫jQuery代碼
5 </script>
6 </body>
引入jQuery的注意事項
剛剛學習jQuery的時候,可以與css做比較:css使用【選擇器】查找元素,使用【屬性名:屬性值】改變元素樣式。jQuery與之類似,可以使用【jQuery選擇器】查找元素,然后使用【jQuery方法】操作元素。這里的操作不只可以操作元素的樣式,還可以添加和刪除元素,或者獲取元素的屬性和文本等等功能。
改變元素樣式
jQuery選擇器和css選擇器很類似(其實可以理解為jQuery選擇器擴展了css選擇器,在$()中添加css選擇器就能找到我們想要的元素),下面我們使用jQuery選擇器和css方法來找到并且改變一個元素的樣式。
1 <body>
2 <h1>hello jquery</h1>
3 <script src="script/jquery.js"></script>
4 <script>
5 $("h1").css("color","red"); //將選擇器$("h1")找到的元素的樣式color設置成紅色
6 </script>
7 </body>
獲取元素文本
上個例子中我們使用了一個jQuery的元素選擇器和css方法實現了改變元素樣式,接下來我們使用類選擇器和text方法獲取元素文本。
1 <body>
2 <h1 class="title">hello jquery</h1>
3 <script src="script/jquery.js"></script>
4 <script>
5 var txt=$(".title").text();
6 console.log(txt);
7 </script>
8 </body>
設置元素屬性
我們還可以通過jQuery的attr方法來設置元素的屬性,下面的例子我們使用attr方法將img標簽的src屬性指定成一張圖片的路徑。
1 <body>
2 <img class="pic" src="">
3 <script src="script/jquery.js"></script>
4 <script>
5 $(".pic").attr("src","images/0.jpg");
6 </script>
7 </body>
添加和刪除class
在說添加和刪除class之前,我們先來看一個略復雜的選擇器,代碼如下所示。
1 <body>
2 <ul class="nav">
3 <li>香蕉</li>
4 <li>蘋果</li>
5 <li>鴨梨</li>
6 </ul>
7 <script src="script/jquery.js"></script>
8 <script>
9 $(".nav li:eq(1)").css("background-color","red");
10 </script>
11 </body>
上面的選擇器$(".nav li:eq(1)")我們可以將其拆分來理解
在上面的代碼中,我們將第二個li元素背景設置成了紅色。
我們經常會使用jQuery操作元素的樣式,上面我們已經學習了css方法,但是在實際開發中,css方法并不常用,我們更多的是使用addClass和removeClass方法來操作元素的樣式,示例代碼如下所示。
【融職教育】在工作中學習,在學習中工作
*請認真填寫需求信息,我們會在24小時內與您取得聯系。