function list(arr){ if(Object.prototype.toString.call(arr) !== '\[object Array\]') return 'arr is not an Array'; let newArr=\[\]; arr.forEach(element=>{ if(element.name){ newArr.push(element.name) }else{ console.log('arr is not contained name'); } }); let last=newArr.pop(); let str=newArr.join(','); if(last===undefined) return ''; if(newArr.length===0) return last; str+=' & '+last; return str; }
function maxStrLength(str){ let i=0,res=0,n=0; for(let j=0;j<str.length;j++){ n=str.slice(i,j).indexOf(str\[j\]); if(n==-1){ res=Math.max(res,j+1-i); }else{ i+=n+1; } } return res; }
行內元素:a、b、span、img、input、strong、select、label、em、button、textarea 塊級元素:div、ul、li、dl、dt、dd、p、h1-h六、blockquote 空元素:即系沒有內容的HTML元素,例如:br、meta、hr、link、input、img
\- 選擇器類型: - ID #id - class .class - 標籤 p - 通用 \* - 屬性 \[type="text"\] - 僞類 :hover - 僞元素 ::first-line - 子選擇器、相鄰選擇器 \- 權重計算規則: - 第一等:表明內聯樣式,如: style=」」,權值爲1000。 - 第二等:表明ID選擇器,如:#content,權值爲0100。 - 第三等:表明類,僞類和屬性選擇器,如.content,權值爲0010。 - 第四等:表明類型選擇器和僞元素選擇器,如div p,權值爲0001。 - 通配符、子選擇器、相鄰選擇器等的。如\*、>、+,權值爲0000。 - 繼承的樣式沒有權值。
function getXHR() { //html元素事件觸發的函數 var myXMLHttpRequest = null; if (window.ActiveXObject) { myXMLHttpRequest = new ActiveXObject("Microsoft.XMLHTTP"); } else { myXMLHttpRequest = new XMLHttpRequest(); } var url = "xxx.php"; var data = "key=val"; //val通常是從某個html元素中取出的value值 myXMLHttpRequest.open("post", url, true); myXMLHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); myXMLHttpRequest.onreadystatechange = function(){ if (myXMLHttpRequest.readyState == 4 && myXMLHttpRequest.status == 200) { var res = myXMLHttpRequest.responseText; var jsonObj = eval("("+res+")"); //接下來就可使用jsonObj這個json對象取出其中的屬性值,作一些修改html元素value值等操做了。 } } myXMLHttpRequest.send(data); }
jQueryjavascript
response.write("{ username : '"+username+"' , content : '"+content+"'}") 因爲服務器端返回的數據格式是JSON文檔,所以也須要對文檔的數據進行處理,可是JSON文檔比較XML文檔更容易解析。 $.ajax({ type:"POST", url:"Handler.ashx", dataType:json, data:{username:$("#name").val(),password:$("#pwd").val()}, success:function(data){ var username = data.username; var content = data.content; var txtHtml = "<div class='comment'><h6>"+ username+":</h6><p class='para'>"+content+"</p></div>"; $("#result").html(txtHtml) } } \`\`\` #### 請用僞代碼描述一個排序算法 快速排序 \`\`\` function quickSort(arr,left,right){ let len=arr.length, partitionIndex, left=typeof left != 'number' ? 0 : left, right=typeof right != 'number' ? len-1 : right; if(left<right){ partitionIndex=partition(arr,left,right); quickSort(arr,left,partitionIndex-1); quickSort(arr,partitionIndex+1,right); } return arr; } function partition(arr,left,right){ let pivot=left, index=pivot+1; for(let 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){ let temp=arr\[i\]; arr\[i\]=arr\[j\]; arr\[j\]=temp; }
https://www.jianshu.com/p/1fb...php
{} new Object() 使用字面量 工廠模式 構造函數模式(constructor) 原型模式(prototype) 構造函數+原型模式 \`\`\` ### 原生js #### 請簡述一下js的原型和原型鏈 \`\`\` 什麼是原型鏈:只要是對象就有原型, 而且原型也是對象, 所以只要定義了一個對象, 那麼就能夠找到他的原型, 如此反覆, 就能夠構成一個對象的序列, 這個結構就被稱爲原型鏈 全部的實例有一個內部指針(prototype),指向它的原型對象,而且能夠訪問原型對象上的全部屬性和方法。
6種css
方式一:藉助構造函數實現繼承 這裏使用的原理就是在Child裏面,把Parent的this指向改成是Child的this指向,從而實現繼承 function Parent(name){ this.name=name; } Parent.prototype.saiHi=function(){ console.log("hello") } function Child(name,age,gender){ Parent.call(this,name) this.age=age; this.gender=gender; } let child=new Child("王磊",20,"男") console.log(child.name);// 王磊 child.sayHi(); // Uncaught TypeError:child.sayHi is not a function 缺點:只能解決屬性的繼承,使用屬性的值不重複,可是父級類別的方法不能繼承 方式二:藉助原型鏈實現繼承 第二種方式就是把Child的原型改成是Parent的實例,從而實現繼承 function Parent(name,gender){ this.name=name; this.gender=gender; this.list=\[1,2,3\] } Parent.prototype.eat=function(){ console.log("晚餐時間到") } function Child(age){ this.age=age; } Child.prototype=new Parent("李白","男"); var child=new Child(20); var child2=new Child(30); child.eat(); console.log(child.list,child2.list);// \[1,2,3\] \[1,2,3\] child.list.push(4) console.log(child.list);// \[1,2,3,4\] console.log(child2.list);// \[1,2,3,4\] 缺點:由於Child的原型對象都是New Parent,因此實例化出來的對象的屬性都是同樣的,並且Parent上面的引用類型只要有一個實例對象修改了,其餘也會跟着修改.由於他們原型對象都是共用的 方式三:組合型 方式三的話是結合了方式一和方式二來實現繼承 function Person(school){ this.school=school; } Person.prototype.skill=function(){ console.log("學習"); } function Student(school,name,age,gender){ Parent.call(this,school); this.name=name; this.age=age; this.gender=gender; } Student.prototype=Person.prototype; let student=new Student("廣鐵一中","王菲菲",14,"女"); console.log(Student.prototype===Person.prototype) console.log(student.constructor) 缺點:父類的原型對象調用了兩次,沒有必要,並且student實例的構造函數是來自於Person 方式四:組合方式優化 function Parent(name,play){ this.name=name; this.play=play; } function Child(name,play,age){ Parent.call(this,name,play); this.age=age; } Child.prototype=Parent.prototype; let child=new Child("張三","玩",20); let child2=new Child("李四","吃",10) console.log(child,child2) console.log(child.prototype===child2.prototype); true console.log(child.constructor); // 構造函數指向的是Parent 缺點:child實例的構造函數來自於Parent 方式五: 組方式優化 只是這種方式的話,你必須得理解Object.create()方法的使用,他建立的對象是在原型上面的 function Parent(name,play){ this.name=name; this.play=play; } function Child(name,play,age){ Parent.call(this,name,play); this.age=age; } Child.prototype=Object.create(Parent.prototype);// 隔離了父類和子類的構造函數,父類的添加到了\_\_proto\_\_屬性上 Child.prototype.constructor=Child let child=new Child("張三","玩",20); let child2=new Child("李四","吃",10) console.log(child.constructor)
完整版html
const PENDING='pending'; const FULFILLED='fulfilled'; const REJECTED='rejected'; function MyPromise(fn){ const self=this; self.value=null; self.error=null; self.status=PENDING; self.onFulfilledCallbacks=\[\]; self.onRejectedCallbacks=\[\]; function resolve(value){ if(value instanceof MyPromise){ return value.then(resolve,reject); } if(self.status===PENDING){ setTimeout(()=>{ self.status=FULFILLED; self.value=value; self.onFulfilledCallbacks.forEach((callback)=>callback(self.value)); },0) } } function reject(error){ if(self.status===PENDING){ setTimeout(function(){ self.status=REJECTED; self.error=error; self.onRejectedCallbacks.forEach((callback)=>callback(self.error)) },0) } } try{ fn(resolve,reject); }catch(e){ reject(e); } } function resolvePromise(bridgepromise,x,resolve,reject){ if(bridgepromise===x){ return reject(new TypeError('Circular reference')); } let called=false; if(x instanceof MyPromise){ if(x.status===PENDING){ x.then(y=>{ resolvePromise(bridgepromise,y,resolve,reject) },error=>{ reject(error); }) }else{ x.then(resolve,reject) } }else if(x!=null && ((typeof x === 'object') || (typeof x === 'function'))){ try{ let then=x.then; if(typeof then === 'function'){ then.call(x,y=>{ if(called) return; called=true; resolvePromise(bridgepromise,y,resolve,reject) },error=>{ if(called) return; called=true; reject(error); }) }else{ resolve(x); } }catch(e){ if(called) return; called=true; reject(e); } }else{ resolve(x); } } MyPromise.prototype.then=function(onFulfilled,onRejected){ const self=this; let bridgePromise; onFulfilled=typeof onFulfilled==='function'?onFulfilled:value=>value; onRejected=typeof onRejected==='function'?onRejected:error=>{throw error}; if(self.status===FULFILLED){ return bridgePromise=new MyPromise((resolve,reject)=>{ setTimeout(()=>{ try{ let x=onFulfilled(self.value); resolvePromise(bridgePromise,x,resolve,reject); }catch(e){ reject(e); } },0) }) } if(self.status===REJECTED){ return bridgePromise=new MyPromise((resolve,reject)=>{ setTimeout(()=>{ try{ let x=onRejected(self.error); resolvePromise(bridgePromise,x,resolve,reject); }catch(e){ reject(e); } },0) }) } if(self.status===PENDING){ return bridgePromise=new MyPromise((resolve,reject)=>{ self.onFulfilledCallbacks.push((value)=>{ try{ let x=onFulfilled(value); resolvePromise(bridgePromise,x,resolve,reject) }catch(e){ reject(e); } }); self.onRejectedCallbacks.push((error)=>{ try{ let x=onRejected(error); resolvePromise(bridgePromise,x,resolve,reject); }catch(e){ reject(e); } }); }); } } MyPromise.prototype.catch=function(onRejected){ return this.then(null,onRejected); } MyPromise.deferred=function(){ let defer={}; defer.promise=new MyPromise((resolve,reject)=>{ defer.resolve=resolve; defer.reject=reject; }); return defer; } try{ module.exports=MyPromise; }catch(e){}
簡版vue
function myPromise(constructor){ let self=this; self.status='pending'; self.vlaue=undefined; self.reason=undefined; function resolve(value){ if(self.status==='pending'){ self.value=value; self.status='resolved'; } } function reject(reason){ if(self.status==='pending'){ self.reason=reason; self.status='rejected'; } } try{ constructor(resolve,reject); }catch(e){ reject(e); } } myPromise.prototype.then=function(onFullfilled,onRejected){ let self=this; switch(self.status){ case 'resolved': onFullfilled(self.value); break; case 'rejected': onRejected(self.reason); break; default: } }
\- const定義的變量不能夠修改,並且必須初始化 \- var定義的變量能夠修改,若是不初始化會輸出undefined,不會報錯。 \- let是塊級做用域,函數內部使用let定義後,對函數外部無影響。
\- 絕對定位水平垂直居中 <div color: rgb(212, 212, 212);"> width: 500px; height: 300px; margin: auto; top: 0; left: 0; bottom: 0; right: 0; background-color: green;">水平垂直居中</div> \- 水平垂直居中 <div color: rgb(212, 212, 212);"> width:400px; height:200px; top: 50%; left: 50%; margin: -100px 0 0 -200px; background-color: red;">水平垂直居中</div> \- 水平垂直居中 <div color: rgb(212, 212, 212);"> width:300px; height:200px; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: blue;">水平垂直居中</div> \- flex 佈局居中 <div > <div >flex 佈局</div> </div>
<!doctype html> <html> <head> <meta charset="utf-8"> <title>js煙花效果</title> <script type="text/javascript"> document.onclick=function (ev) { var oEvent=ev||event; var aDiv=\[\]; var oDiv=null; var \_oDiv=document.createElement('div'); var i=0; var x=oEvent.clientX; var y=oEvent.clientY; \_oDiv.style.position='absolute'; \_oDiv.style.background='red'; \_oDiv.style.width='3px'; \_oDiv.style.height='30px'; \_oDiv.style.left=oEvent.clientX+'px'; \_oDiv.style.top=document.documentElement.clientHeight+'px'; document.body.appendChild(\_oDiv); var t=setInterval(function (){ if(\_oDiv.offsetTop<=y) { clearInterval(t); show(); document.body.removeChild(\_oDiv); } \_oDiv.style.top=\_oDiv.offsetTop-30+'px'; }, 30); function show() { var oDiv=null; for(i=0;i<100;i++) { oDiv=document.createElement('div'); oDiv.style.width='3px'; oDiv.style.height='3px'; oDiv.style.background='#'+Math.ceil(Math.random()\*0xEFFFFF+0x0FFFFF).toString(16); oDiv.style.position='absolute'; oDiv.style.left=x+'px'; oDiv.style.top=y+'px'; var a=Math.random()\*360; //oDiv.speedX=Math.random()\*40-20; //oDiv.speedY=Math.random()\*40-20; oDiv.speedX=Math.sin(a\*180/Math.PI)\*20\*Math.random(); oDiv.speedY=Math.cos(a\*180/Math.PI)\*20\*Math.random(); document.body.appendChild(oDiv); aDiv.push(oDiv); } } setInterval(doMove, 30); function doMove() { for(i=0;i<aDiv.length;i++) { aDiv\[i\].style.left=aDiv\[i\].offsetLeft+aDiv\[i\].speedX+'px'; aDiv\[i\].style.top=aDiv\[i\].offsetTop+aDiv\[i\].speedY+'px'; aDiv\[i\].speedY+=1; if(aDiv\[i\].offsetLeft<0 || aDiv\[i\].offsetLeft>document.documentElement.clientWidth || aDiv\[i\].offsetTop<0 || aDiv\[i\].offsetTop>document.documentElement.clientHeight) { document.body.removeChild(aDiv\[i\]); aDiv.splice(i, 1); } } } }; </script> </head> <body > </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>css3實現煙花特效</title> <style> \* { margin: 0; padding: 0; } html{ width: 100%; height: 100%; } body{ width: 100%; height: 100%; } #container{ width: 100%; height: 100%; background-color: black; position: relative; } #fireworks{ position: absolute; left: 50%; margin-left: -250px; bottom: 60%; margin-bottom: -180px; transform: scale(0); animation: fireworks 5s 3s; } @keyframes fireworks { 0%{ transform: scale(0); } 80%{ transform: scale(1); } 100%{ opacity: 0; } } #firecracker{ position: absolute; left: 50%; bottom: 0%; margin-left: -4px; animation: firecracker 3s forwards; } @keyframes firecracker { 0%{ transform: scale(1); bottom: 0%; } 100%{ bottom: 60%; transform: scale(0); } } </style> </head> <body> <div id="container"> <div id="fireworks"><img src="imgs/fireworks.png" alt=""></div> <div id="firecracker"><img src="imgs/firecracker.png" alt="" width="8px"></div> </div> </body> </html> \`\`\` ### 框架 #### vue的生命週期都有哪些? \`\`\` Vue 實例從建立到銷燬的過程,就是生命週期。從開始建立、初始化數據、編譯模板、掛載Dom→渲染、更新→渲染、銷燬等一系列過程,稱之爲 Vue 的生命週期。 生命週期中有多個事件鉤子,以下: \- beforeCreate(建立前) 在數據觀測和初始化事件還未開始 \- created(建立後) 完成數據觀測,屬性和方法的運算,初始化事件,$el屬性尚未顯示出來 \- beforeMount(載入前) 在掛載開始以前被調用,相關的render函數首次被調用。實例已完成如下的配置:編譯模板,把data裏面的數據和模板生成html。注意此時尚未掛載html到頁面上。 \- mounted(載入後) 在el 被新建立的 vm.$el 替換,並掛載到實例上去以後調用。實例已完成如下的配置:用上面編譯好的html內容替換el屬性指向的DOM對象。完成模板中的html渲染到html頁面中。此過程當中進行ajax交互。 \- beforeUpdate(更新前) 在數據更新以前調用,發生在虛擬DOM從新渲染和打補丁以前。能夠在該鉤子中進一步地更改狀態,不會觸發附加的重渲染過程。 \- updated(更新後) 在因爲數據更改致使的虛擬DOM從新渲染和打補丁以後調用。調用時,組件DOM已經更新,因此能夠執行依賴於DOM的操做。然而在大多數狀況下,應該避免在此期間更改狀態,由於這可能會致使更新無限循環。該鉤子在服務器端渲染期間不被調用。 \- beforeDestroy(銷燬前) 在實例銷燬以前調用。實例仍然徹底可用。 \- destroyed(銷燬後) 在實例銷燬以後調用。調用後,全部的事件監聽器會被移除,全部的子實例也會被銷燬。該鉤子在服務器端渲染期間不被調用。
開發通用組件是很基礎且重要的工做,通用組件必須具有高性能、低耦合的特性 1、數據從父組件傳入 爲了解耦,子組件自己就不能生成數據。即便生成了,也只能在組件內部運做,不能傳遞出去。 父對子傳參,就須要用到 props,可是通用組件的的應用場景比較複雜,對 props 傳遞的參數應該添加一些驗證規則 2、在父組件處理事件 在通用組件中,一般會須要有各類事件, 好比複選框的 change 事件,或者組件中某個按鈕的 click 事件 這些事件的處理方法應當儘可能放到父組件中,通用組件自己只做爲一箇中轉 3、記得留一個 slot 一個通用組件,每每不可以完美的適應全部應用場景 因此在封裝組件的時候,只須要完成組件 80% 的功能,剩下的 20% 讓父組件經過 solt 解決 4、不要依賴 Vuex 父子組件之間是經過 props 和 自定義事件 來傳參,非父子組件一般會採用 Vuex 傳參 可是 Vuex 的設計初衷是用來管理組件狀態,雖然能夠用來傳參,但並不推薦 由於 Vuex 相似於一個全局變量,會一直佔用內存 在寫入數據龐大的 state 的時候,就會產生內存泄露 5、合理運用 scoped 編寫 CSS 在編寫組件的時候,能夠在 <style> 標籤中添加 scoped,讓標籤中的樣式只對當前組件生效 可是一味的使用 scoped,確定會產生大量的重複代碼 因此在開發的時候,應該避免在組件中寫樣式 當全局樣式寫好以後,再針對每一個組件,經過 scoped 屬性添加組件樣式
\- 父組件向子組件傳值 --Props傳遞數據 在父組件中使用兒子組件 <template> <div> 父組件:{{money}} <Son1 :money="money"><Son1> </div> </template> <script> import Son1 from ''./Son1"; export default{ components:{ Son1 }, data(){ return { money: 100}; } }; </script> 子組件接受數據 props:{ value:{ type:Number, default:1 } } 若是是數組 props:{ value:{ type:Array, default: ()=>\[\] } } \- 子組件通訊父組件 $emit使用 <template> <div> 父組件:{{money}} <Son1 :money="money" @input="change"><Son1> </div> </template> <script> import Son1 from ''./Son1"; export default{ methods:{ change(data){ this.money = data } }, components:{ Son1 }, data(){ return { money: 100}; } }; </script> 子組件觸發綁定本身身上的方法 <template> <div> 子組件1:{{money}} <button @click="$emit('input',200)">修改父組件的值<Son1> </div> </template> <script> export default{ props:{ money:{ type:Number } } }; </script> \- $parent、$children(多層級傳遞) <Grandson1 :value="value"></Grandson1> <template> <div> 孫子1:{{value}} <---調用父組件的input事件--> <button @click="$parent.$emit('input',200)">更改<Son1> </div> </template> <script> export default{ props:{ value:{ type:Number } } }; </script> \- $attrs、 $listeners: $attrs批量向下傳入屬性: <Son2 name="小明" age="18"></Son2> <--能夠在son2組件中使用$attrs,能夠將屬性繼續向下傳遞--> <div> 兒子2:{{ $attrs.name }} <Grandson2 v-bind="$attrs"></Grandson2> </div> <tempalte> <div>孫子:{{$attrs}}</div> </template> $listeners批量向下傳入方法: <Son2 name="小明" age="18" @click=「()=>{this.money =500}」></Son2> <--能夠在son2組件中使用$attrs,能夠將屬性繼續向下傳遞--> <Grandson2 v-bind="$attrs" v-on="$listeners"></Grandson2> <button @click="$listeners.click()">更改<Son1> \- Provide&Inject Provide 在父級中注入數據 provide(){ return {parentMsg:'父親'}; } Inject 在任意子組件中能夠注入父級數據 inject:\['parentMsg'\]//會將數據掛載在當前實例上 \- ref使用 <Grandson2 name="花花" ref="grand2"></Grandson2> mounted(){ console.log(this.$refs.grand2.name); } \- EventBus:用於跨組件通知 Vue.prototype.$bus = new Vue(); Son2組件和Grandson1互相通訊 mounted() { //父親組件註冊 this.$bus.$on('my',data=>{ console.log(data) }) } mounted(){ //侄子組件調用 this.$nextTick(()=>{ this.$bus.$emit('my',"我是小紅」); }) }
http://dongfanker.coding.me/2...java
爲何須要Bus 通常來講,都是利用父組件給子組件使用query或者params傳遞參數來實現子組件的數據顯示 不過,當出現子組件須要向父組件傳遞數據的時候,就須要用到bus,bus能夠本身建立,也能夠經過裝包來實現 直接建立Bus 在此處直接將Bus注入Vue對象中,成爲全局的組件。 在子組件中經過this.$root.Bus.$on(key,method),this.$root.Bus.$emit(key,data)來調用 將$on放在mounted,created這些鉤子函數中,相應的函數使用(e)=>{function}比較便捷 1 2 3 4 5 6 7 8 9 10 import Vue from 'vue' const Bus = new Vue() var app= new Vue({ el:'#app', data:{ Bus } }) 使用vue-bus 使用yarn或者npm安裝vue-bus以後,在main.js中引用它 1 2 import VueBus from 'vue-bus'; Vue.use(VueBus); 因而調用直接能夠寫爲 this.$bus.on(key, this.method),this.$bus.emit(key, { text: …… } 其中第一個字符串參數表明key,每一個key都可以實現本身的獨立傳輸,this.method爲事先定義好的method,用於對傳入的數據進行處理 爲何使用vuex 當咱們的應用遇到多個組件共享狀態時,會須要: 多個組件依賴於同一狀態。 來自不一樣組件的行爲須要變動同一狀態。 通過個人觀察,vuex在其中的做用就是組件與狀態的捆綁剝離開來,使得組件狀態的改變依賴於某個行爲,這使得代碼變得易於調試。 Vuex採用集中式存儲管理應用的全部組件的狀態,這裏的關鍵在於集中式存儲管理。這意味着原本須要共享狀態的更新是須要組件之間通信的,而如今有了vuex,就組件就都和store通信了。 使用vuex 使用yarn或者npm安裝vuex以後,在main.js中引用它 1 2 3 4 5 6 7 import Vuex from 'vuex' import store from './vuex/store' Vue.use(Vuex) new Vue({ el: '#app', store }) 隨後建立vuex目錄,將store.js放在目錄下,定義state和mutation 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state: { author: 'Wise Wrong' }, mutations:{ newAuthor(state,msg){ state.author = msg } } }) export default store 在使用的時候,不直接修改this.$store.state.author,而是使用this.$store.commit()來提交,可讓咱們更好的跟蹤每個狀態的變化,在大型項目中更爲適用