百度提前批-百度智能小程序(面经详解)
文章目錄
- 百度提前批-百度智能小程序(面經詳解)
- 1、定位
- 2、z-index 、層疊
- 3、作用域(scope)
- 4、單例模式
- 5、原型鏈
- 6、繼承(借用構造函數,寄生組合繼承,缺點是什么)
- 7、閉包
- 8、Vue生命周期(父子生命周期,每個生命周期都發生了什么)
- 9、Vuex
- 10、slot插槽
- 11、TCP三次握手四次揮手
- 12、前端性能優化
- 13、瀏覽器緩存
- 14、快速排序
- 15、移動端適配rem em
在牛客網看面經時隨機找的一個面經,將問到的知識點詳細介紹概括了一下,有一些知識點參見其他博客,希望能幫助到更多人,最后大家一起學習進步,加油!
百度提前批-百度智能小程序(面經詳解)
1、定位
? 默認為static,也就是按照文檔的流式(flow)定位,將元素放到一個合適的位置,所以在不同的分辨率下,采用流式定位能很好的自適應。可指定相對位移(margin、padding)。
? relative(相對定位),相對于元素自己本身的定位,注意:相對定位的元素仍然在文檔流中,仍然占據著它本來占據的位置空間--雖然它現在已經不在本來的位置了。可指定相對位移(left、right、top、bottom)。
? absolute(絕對定位),將某個元素放到指定的位置,使用left、right、top、bottom來定位,如果沒有父元素,則其位置是相對于body來定位的。注意:絕對定位會使元素從文檔流中被刪除,結果就是該元素原本占據的空間被其它元素所填充。
? fixed(固定定位),fixed定位的參照物總是當前的文檔。
? float(浮動),1)浮動會將元素從文檔流中刪除,他的空間會被其它元素補上;2)浮動的參數物是父元素,是在父元素這個容器中飄;3)為了清除浮動造成的對浮動元素之后元素的影響,我們在浮動元素之后加一個div,并將這個div的clear設置為both。
2、z-index 、層疊
? 默認層疊順序原則:同級元素中,后面的元素覆蓋前面的元素;父子元素中,子元素覆蓋父元素
? z-index可控制層疊順序,但要在其css中添加一個position屬性,注意:其值不能為static
3、作用域(scope)
? ES5 全局作用域 局部作用域 ES6添加塊級作用域(let、const)
let 不存在變量提升(即不能先使用后聲明)、同一個作用域下不能重復定義同樣的名稱、有著嚴格的作用域===塊級作用域{} const 聲明的一個只讀的常量,一旦聲明,常量的值就不能改變、const一旦聲明了就得初始化,不能只聲明不賦值 var x = 10; //全局作用域function f1(){var y = 100; //局部作用域 console.log(x)};function f2(){var z = 1000; //局部作用域 console.log(x)};console.log(y);重點:
? 全局變量和局部變量不同名時,作用域是整個程序
? 全局變量和局部變量同名時(同時var),全局變量的作用域不包含同名局部變量的作用域
// 面試題var a = 10;function f1(){var b = 2*a; //2*undefined ==>NANvar a = 20;var c = a+1; //21console.log(b);console.log(c);};f1();4、單例模式
? (設計模式)
//單例(單一的實例) //在系統中只能有且只有一個實例, 如資源管理器 //前端如何使用? 如頁面上需要多個彈框,需要限制只能有一個(應用場景)//例子: <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>單例應用</title> </head> <body><button id="btn">打開彈框</button><script>//創建一個div// var createWindow = function(){// var div = document.createElement("div");//在內存中生成一個div// div.innerHTML = "我是彈框,彈框應該唯一"; //給div加內容// div.style.display = "none"; //默認隱藏// document.body.appendChild(div);//把div寫入頁面// return div;// }// btn.onclick = function(){// var win = createWindow(); //創建彈框// win.style.display = "block"; //顯示彈框// }//缺點:每一次createWindow()都會在內存中生成一個div副本,沒有必要//可以使用單例思想重構//使用單例模式重構var createWindow = (function(){var div;return function(){ //閉包===函數+外部局部變量(緩存)if (!div) { //若div不存在則創建,否則直接返回div = document.createElement("div");//在內存中生成一個divdiv.innerHTML = "我是彈框,彈框應該唯一"; //給div加內容div.style.display = "none"; //默認隱藏document.body.appendChild(div);//把div寫入頁面}return div;}})(); //()表示執行btn.onclick = function(){var win = createWindow(); //創建彈框 //等價于29的functionwin.style.display = "block"; //顯示彈框}</script> </body> </html>5、原型鏈
? 原型的理解:原型是一個對象 其它對象可以通過它實現屬性繼承。對象分二種:普通對象和函數對象,prototype是函數對象才擁有的屬性。
注意:
//總結: //每一個函數對象都有一個prototype屬性,但是普通對象沒有;prototype下面又有constructor,指向這個函數; //每一個對象都有一個__proto__內部屬性,指向它所對應的構造函數的原型對象;? 原型鏈:
//原型鏈 function F1(){this.name1 = 'f1' }; F1.prototype.name = 'object'; function F2(){this.name2= 'f2' }; function F3(){this.name3 = 'f3' }; F2.prototype = new F1(); //f2的原型是f1 F3.prototype = new F2(); //f3的原型是f2 var f = new F3(); //實例化的處理 f.name1; //修改 f.__proto__.__proto__.__proto__.name= '12414'; //刪除 delete f.__proto__.__proto__.__proto__.name;6、繼承(借用構造函數,寄生組合繼承,缺點是什么)
//原型繼承 function Animal(){this.name = "動物名";this.color=['red','yellow']; }; Animal.prototype.sayName=function (name){return this.name;}; function Cat(){ }; Cat.prototype = new Animal(); var c1 = new Cat(); var c2 = new Cat(); c1.sayName("c1") //"動物名" c1.color.push('blue'); c2.color //['red','yellow','blue']原型繼承缺點:原型對象上的屬性和方法都能被實例對象共享
問題:1.不能傳參 2.父類中的屬性和方法一旦賦值給子類的原型屬性,這些父類的屬性和方法都屬于子類的共享屬性,修改引用類型(array、object、function)的數據會影響所有子實例的值
//將父對象的構造函數綁定在子對象上 在子類的構造函數內部中調用父類的構造函數 function Animal(name){this.name = name;this.color=['red','yellow']; }; Animal.prototype.sayName=function (name){return this.name; }; function Dog (name) {Animal.call(this,name) //Animal在當前Dog對象中執行 }; var d1 = new Dog('lll'); var d2 = new Dog('555');d1.color.push('blue');console.log(d1.color);//(3) ["red", "yellow", "blue"] console.log(d1.name);//lllconsole.log(d2.color);//(2) ["red", "yellow"] console.log(d2.name);//555console.log(d1.sayName);//undefined構造函數繼承解決了原型對象中包含引用類型值所帶來問題
缺點:不能繼承父類的原型對象上的方法
//解決方法--組合繼承 function Animal(name){this.name = name;this.color=['red','yellow']; }; Animal.prototype.sayName=function (name){return this.name; };function Dog (name) {//讓父類的屬性值繼承下來,修改父類的引用類型的值,不會影響其他實例的引用類型的值Animal.call(this,name) }; //重寫原型對象,把父類共享的方法繼承下來 Dog.prototype = new Animal(); Dog.prototype.constructor=Dog;//原型繼承會將子類原型上的constructor屬性丟失,這里加上var d1 = new Dog('lll'); var d2 = new Dog('555');d1.color.push('blue');console.log(d1.color); //打印出(3) ["red", "yellow", "blue"] console.log(d1.name); //打印出lllconsole.log(d2.color); //打印出(2) ["red", "yellow"] console.log(d2.name); //打印出555console.log(d1.sayName); //打印出?(name){return this.name;}組合繼承問題:會調用父類構造函數2次
//寄生組合式繼承 --- 解決了組合繼承調用父類構造函數2次問題 function Animal(name){this.name = name;this.color=['red','yellow']; }; Animal.prototype.sayName=function (name){return this.name; };function Dog (name) {//讓父類的屬性值繼承下來,修改父類的引用類型的值,不會影響其他實例的引用類型的值Animal.call(this,name) }; //重寫原型對象,把父類共享的方法繼承下來 Dog.prototype = Object.create(Anmail.prototype) //解決了組合方式重復訪問父類構造函數 Dog.prototype.constructor=Dog;//原型繼承會將子類原型上的constructor屬性丟失,這里加上var d1 = new Dog('lll'); var d2 = new Dog('555');d1.color.push('blue');console.log(d1.color); //打印出(3) ["red", "yellow", "blue"] console.log(d1.name); //打印出lllconsole.log(d2.color); //打印出(2) ["red", "yellow"] console.log(d2.name); //打印出555console.log(d1.sayName); //打印出?(name){return this.name;}7、閉包
閉包:簡單來說就是: 一個函數引用函數外部局部變量
由于在javascript中,只有函數內部的子函數才能讀取局部變量,所以說,閉包可以簡單理解成“定義在一個函數內部的函數“。所以,在本質上,閉包是將函數內部和函數外部連接起來的橋梁。
//閉包一 function f1(){var a = 10; //相對于f2外部局部變量function f2() { //f2可以訪問aconsole.log(a)}f2(); } f1();//閉包二 function a(){var n = 0; //外部局部變量this.add = function(){//函數引用外部局部變量n++;console.log(n)} } var c = new a(); console.log(c.n) //undefined 因為n是局部 c.add(); //1 c.add(); //2//閉包三 function a(){var n = 0; //外部局部變量function add(){//函數引用外部局部變量n++;console.log(n)}return add; } a()() //柯里化格式 a()()()()()//閉包四 可以多次執行 var a = function(){var n = 0;return function(){ //閉包 匿名函數賦給an++;console.log(n);} }; var b = a(); //b---閉包 var c = a(); //c---閉包 b(); //1 c(); //1//閉包有什么用 //對象封裝 能夠將name緩存起來,避免污染 var Person = function(){var name = "張三"; //get set 相當于對這個屬性的操作return {getName: function(){//匿名函數 閉包return name;},setName: function(newName) {//匿名函數 閉包name = newName;}} }(); //加上這個括號表示立即執行 Person == {.....} console.log(Person.getName()) //張三 Person.setName("xxxxx"); console.log(Person.getName()) //xxxxx//繼承 人-----白人 黑人 var Person = function(){var name = "張三"; //get set 相當于對這個屬性的操作return {getName: function(){//匿名函數 閉包return name;},setName: function(newName) {//匿名函數 閉包name = newName;}} }; var BlackPerson = function (){} BlackPerson.prototype = Person(); //為什么不需要new() 因為已經是一個實例對象(字面量對象) var p = new BlackPerson(); //p是一個對象,對象中有getName函數,函數引用name形成閉包 p.setName("yyyy"); console.log(p.getName())總結: //閉包 難----變化太多 有很多種用法 不難----一個函數引用函數外部局部變量 //原型 在你身上找不到---去原型上找----繼續去原型的原型上找//什么場景 需要維護一個函數的一些信息不變, 可以一直存在 被緩存 //可以多層嵌套 看你怎么使用//缺點: 忽略 //不易理解, 占用內存//優點: //可以緩存數據, 封裝, 柯里化, 很靈活《JavaScript高級編程》書中建議:由于閉包會攜帶包含它的函數的作用域,因為會比其他函數占用更多內容,過度使用閉包,會導致內存占用過多。
8、Vue生命周期(父子生命周期,每個生命周期都發生了什么)
它可以總共分為8個階段:創建前/后, 載入前/后,更新前/后,銷毀前/銷毀后:
| beforeCreate----創建前 | 組件實例更被創建,組件屬性計算之前,數據對象data都為undefined,未初始化。 |
| created----創建后 | 組件實例創建完成,屬性已經綁定,數據對象data已存在,但dom未生成,$el未存在 |
| beforeMount—掛載前 | vue實例的$el和data都已初始化,掛載之前為虛擬的dom節點,data.message未替換 |
| mounted-----掛載后 | vue實例掛載完成,data.message成功渲染 |
| beforeUpdate----更新前 | 當data變化時,會觸發beforeUpdate方法 |
| updated----更新后 | 當data變化時,會觸發updated方法 |
| beforeDestory—銷毀前 | 組件銷毀之前調用 |
| destoryed—銷毀后 | 組件銷毀之后調用,對data的改變不會再觸發周期函數,vue實例已解除事件監聽和dom綁定,但dom結構依然存在 |
9、Vuex
實例:
import Vue from 'vue' import Vuex from 'vuex'Vue.use(Vuex)const state = {num:100, flag:true }; const getters={ //store對象中的計算屬性a(state){return state.num % 2 ==0 ?'偶數':'奇數'},b(state){return state.num +=10}, }; const actions = { ADD({commit,state}){ //context就是$storecommit('ADD');},DEL({commit,state}){ //context就是$storecommit('DEL');} };const mutations = { ADD(state){state.num+=1;},DEL(state){state.num-=1;} };export default new Vuex.Store({state,getters,mutations,actions })vue代碼:
<template><div class="home"><!-- 直接獲取store中的state -->{{$store.state.num}}<!-- 直接獲取store中的getters -->{{$store.getters.a}}<!-- 直接觸發store中的mutations--><button @click="$store.commit('ADD')">添加</button><button @click="del()">減少</button><!-- {{isEvenOrOdd}} --><h1>輔助函數:{{b}}</h1><button @click="ADD">添加</button><button @click="DEL">減少</button></div> </template><script> //輔助函數 mapGetters mapActions import {mapState, mapGetters,mapActions } from 'vuex'export default {name: 'Home',//methods:mapActions(['ADD','DEL']), //沒有其它事件的處理methods:{...mapActions(['ADD','DEL']),del(){this.$store.dispatch('DEL'); //觸發actions},increment(){this.$store.dispatch('ADD'); },decrement(){this.$store.dispatch('DEL'); }},//computed:mapGetters(['a','b']) //沒有其它狀態的處理computed:{// ...mapState({// num:state=>state.num// }),...mapGetters(['a','b']) ,add(){return this.$store.state.num+10},isEvenOrOdd(){return this.$store.state.num % 2 ==0 ?'偶數':'奇數'}} } </script>10、slot插槽
- 插槽最基本的用法就是允許我們想一個組件中插入一些html代碼
- 有了插槽我們便可以向組件標簽內寫html代碼
可參見博客
11、TCP三次握手四次揮手
序列號seq:占4個字節,用來標記數據段的順序,TCP把連接中發送的所有數據字節都編上一個序號,第一個字節的編號由本地隨機產生;給字節編上序號后,就給每一個報文段指派一個序號;序列號seq就是這個報文段中的第一個字節的數據編號。
確認號ack:占4個字節,期待收到對方下一個報文段的第一個數據字節的序號;序列號表示報文段攜帶數據的第一個字節的編號;而確認號指的是期望接收到下一個字節的編號;因此當前報文段最后一個字節的編號+1即為確認號。
確認ACK:占1位,僅當ACK=1時,確認號字段才有效。ACK=0時,確認號無效
同步SYN:連接建立時用于同步序號。當SYN=1,ACK=0時表示:這是一個連接請求報文段。若同意連接,則在響應報文段中使得SYN=1,ACK=1。因此,SYN=1表示這是一個連接請求,或連接接受報文。SYN這個標志位只有在TCP建產連接時才會被置1,握手完成后SYN標志位被置0。
終止FIN:用來釋放一個連接。FIN=1表示:此報文段的發送方的數據已經發送完畢,并要求釋放運輸連接
? PS:ACK、SYN和FIN這些大寫的單詞表示標志位,其值要么是1,要么是0;ack、seq小寫的單詞表示序號。
三次握手過程:
第一次握手:建立連接時,客戶端發送syn包(syn=j)到服務器,并進入SYN_SENT狀態,等待服務器確認;SYN:同步序列編號(Synchronize Sequence Numbers)。第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED(TCP連接成功)狀態,完成三次握手。四次揮手過程:
1)客戶端進程發出連接釋放報文,并且停止發送數據。釋放數據報文首部,FIN=1,其序列號為seq=u(等于前 面已經傳送過來的數據的最后一個字節的序號加1),此時,客戶端進入FIN-WAIT-1(終止等待1)狀態。 TCP規 定,FIN報文段即使不攜帶數據,也要消耗一個序號。 2)服務器收到連接釋放報文,發出確認報文,ACK=1,ack=u+1,并且帶上自己的序列號seq=v,此時,服務端就 進入了CLOSE-WAIT(關閉等待)狀態。TCP服務器通知高層的應用進程,客戶端向服務器的方向就釋放了,這時 候處于半關閉狀態,即客戶端已經沒有數據要發送了,但是服務器若發送數據,客戶端依然要接受。這個狀態還 要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間。 3)客戶端收到服務器的確認請求后,此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態,等待服務器發送連接 釋放報文(在這之前還需要接受服務器發送的最后的數據)。 4)服務器將最后的數據發送完畢后,就向客戶端發送連接釋放報文,FIN=1,ack=u+1,由于在半關閉狀態,服 務器很可能又發送了一些數據,假定此時的序列號為seq=w,此時,服務器就進入了LAST-ACK(最后確認)狀 態,等待客戶端的確認。 5)客戶端收到服務器的連接釋放報文后,必須發出確認,ACK=1,ack=w+1,而自己的序列號是seq=u+1,此時, 客戶端就進入了TIME-WAIT(時間等待)狀態。注意此時TCP連接還沒有釋放,必須經過2??MSL(最長報文段壽 命)的時間后,當客戶端撤銷相應的TCB后,才進入CLOSED狀態。 6)服務器只要收到了客戶端發出的確認,立即進入CLOSED狀態。同樣,撤銷TCB后,就結束了這次的TCP連接。 可以看到,服務器結束TCP連接的時間要比客戶端早一些。常見面試題目:
【問題1】為什么連接的時候是三次握手,關閉的時候卻是四次握手?
答:因為當Server端收到Client端的SYN連接請求報文后,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的, SYN報文是用來同步的。但是關閉連接時,當Server端收到FIN報文時,很可能并不會立即關閉SOCKET,所以只能先 回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端所有的報文都發送完了,我才能發 送FIN報文,因此不能一起發送。故需要四步握手。【問題2】為什么TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?
答:雖然按道理,四個報文都發送完畢,我們可以直接進入CLOSE狀態了,但是我們必須假象網絡是不可靠的,有可以 最后一個ACK丟失。所以TIME_WAIT狀態就是用來重發可能丟失的ACK報文。在Client發送出最后的ACK回復,但該 ACK可能丟失。Server如果沒有收到ACK,將不斷重復發送FIN片段。所以Client不能立即關閉,它必須確認Server接收 到了該ACK。Client會在發送出ACK之后進入到TIME_WAIT狀態。Client會設置一個計時器,等待2MSL的時間。如果在 該時間內再次收到FIN,那么Client會重發ACK并再次等待2MSL。所謂的2MSL是兩倍的MSL(Maximum Segment Lifetime)。MSL指一個片段在網絡中最大的存活時間,2MSL就是一個發送和一個回復所需的最大時間。如果直到 2MSL,Client都沒有再次收到FIN,那么Client推斷ACK已經被成功接收,則結束TCP連接。【問題3】為什么不能用兩次握手進行連接?
答:3次握手完成兩個重要的功能,既要雙方做好發送數據的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始 序列號進行協商,這個序列號在握手過程中被發送和確認。現在把三次握手改成僅需要兩次握手,死鎖是可能發生的。作為例子,考慮計算機S和C之間的通信,假定C給S發送 一個連接請求分組,S收到了這個分組,并發 送了確認應答分組。按照兩次握手的協定,S認為連接已經成功地建立 了,可以開始發送數據分組。可是,C在S的應答分組在傳輸中被丟失的情況下,將不知道S是否已準備好,不知道S建 立什么樣的序列號,C甚至懷疑S是否收到自己的連接請求分組。在這種情況下,C認為連接還未建立成功,將忽略S發 來的任何數據分組,只等待連接確認應答分組。而S在發出的分組超時后,重復發送同樣的分組。這樣就形成了死鎖。【問題4】如果已經建立了連接,但是客戶端突然出現故障了怎么辦?
TCP還設有一個保活計時器,顯然,客戶端如果出現故障,服務器不能一直等下去,白白浪費資源。服務器每收到一次 客戶端的請求后都會重新復位這個計時器,時間通常是設置為2小時,若兩小時還沒有收到客戶端的任何數據,服務器就 會發送一個探測報文段,以后每隔75秒鐘發送一次。若一連發送10個探測報文仍然沒反應,服務器就認為客戶端出了故 障,接著就關閉連接。參考博文
12、前端性能優化
- 減少http請求次數:CSS Sprites, JS、CSS源碼壓縮、圖片大小控制合適;網頁Gzip,CDN托管,data緩存 ,圖片服務器。
- 前端模板 JS+數據,減少由于HTML標簽導致的帶寬浪費,前端用變量保存AJAX請求結果,每次操作本地變量,不用請求,減少請求次數。
- 用innerHTML代替DOM操作,減少DOM操作次數,優化javascript性能。
- 當需要設置的樣式很多時設置className而不是直接操作style。
- 少用全局變量、緩存DOM節點查找的結果。減少IO讀取操作。
- 避免使用CSS Expression(css表達式)又稱Dynamic properties(動態屬性)。
- 圖片預加載,將樣式表放在頂部,將腳本放在底部加上時間戳。
- 避免在頁面的主體布局中使用table,table要等其中的內容完全下載之后才會顯示出來,顯示比div+css布局慢。
? 對普通的網站有一個統一的思路,就是盡量向前端優化、減少數據庫操作、減少磁盤IO。向前端優化指的是,在不影響功能和體驗的情況下,能在瀏覽器執行的不要在服務端執行,能在緩存服務器上直接返回的不要到應用服務器,程序能直接取得的結果不要到外部取得,本機內能取得的數據不要到遠程取,內存能取到的不要到磁盤取,緩存中有的不要去數據庫查詢。減少數據庫操作指減少更新次數、緩存結果減少查詢次數、將數據庫執行的操作盡可能的讓你的程序完成(例如join查詢),減少磁盤IO指盡量不使用文件系統作為緩存、減少讀寫文件次數等。程序優化永遠要優化慢的部分,換語言是無法“優化”的。
? 詳細可點擊查看此博客(前端工程師面試題(性能優化)
13、瀏覽器緩存
這里了解得不是很多 所謂的http緩存,就是瀏覽器自己給你的一個功能,一個緩存數據庫,夾在服務端和客戶端中間,你只需要設 置一些參數即可實現 緩存/不緩存/時效內緩存/時效外緩存等(默認存在緩存)參見博文
參見博文
14、快速排序
快速排序的基本思想:通過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。
快速排序使用分治法來把一個串(list)分為兩個子串(sub-lists)。具體算法描述如下:
- 從數列中挑出一個元素,稱為 “基準”(pivot);
- 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的后面(相同的數可以到任一邊)。在這個分區退出之后,該基準就處于數列的中間位置。這個稱為分區(partition)操作;
- 遞歸地(recursive)把小于基準值元素的子數列和大于基準值元素的子數列排序。
代碼實現:
function quickSort(arr,left,right){var len = arr.length;var left = typeof left != 'number' ? 0:left;var right = typeof right != 'number' ? len-1:left;if(left < right){var partitionIndex = partition(arr,left,right);quickSort(arr,left,partitionIndex-1);quickSort(arr,partitionIndex+1,right);} } function partition(arr,left,right){ //分區操作var pivot = left,index = pivot+1; //pivot是基準(比較的那個數);index則是向右移動,每次循環記錄比基準數小的數的個數,最后交換pivot與index-1,則把arr分成小于pivot的和大于pivot的兩個分區for(var i=index;i<=right;i++){if(arr[i]<arr[pivot]){swap(arr,i,index);index++;}}swap(arr,pivot,index-1);return index-1; } function swap(arr,i,j){ //交換位置var temp=arr[i];arr[i]=arr[j];arr[j]=temp; }參見博客
15、移動端適配rem em
rem是(font size of the root element),意思就是根據網頁的根元素來設置字體大小,和 em(font size of the element)的區別是,em是根據其父元素的字體大小來設置,而 rem 是根據網頁的根元素(html)來設置字體大小的。(以設置字體大小為例,同樣可用于width、margin等)
改相關的字體配置,都是默認顯示 font-size 是 16px 即:
html {font-size:16px; }那么如果我們想給一個 p 標簽設置 12px 字體大小那么用 rem 來寫就是:
p {font-size: 0.75rem; //12÷16=0.75(rem) }參見博文
總結
以上是生活随笔為你收集整理的百度提前批-百度智能小程序(面经详解)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: leetcode练习(简单总结做过的题)
- 下一篇: Github上传代码截图过程