JS的單線程模型和事件循環(huán)機(jī)制
JS的單線程模型意味著签杈,在執(zhí)行JS時(shí)只有一個(gè)主線程,每個(gè)任務(wù)必須順序執(zhí)行汞斧。如果當(dāng)前任務(wù)執(zhí)行時(shí)間過長滔驶,會導(dǎo)致接下來的所有任務(wù)都處于阻塞狀態(tài)遇革,進(jìn)而導(dǎo)致瀏覽器卡死等我們不希望看到的狀況。為了解決這一問題,事件循環(huán)機(jī)制(Event Loop)被發(fā)明出來萝快。
事件循環(huán)機(jī)制中锻霎,負(fù)責(zé)執(zhí)行JS腳本的單線程我們稱為主線程,在內(nèi)存中表現(xiàn)為一個(gè)執(zhí)行棧揪漩,JS只通過主線程執(zhí)行任務(wù)旋恼。異步任務(wù)被掛起,存儲在堆中氢拥,當(dāng)異步任務(wù)準(zhǔn)備就緒,它對應(yīng)的事件便進(jìn)入任務(wù)隊(duì)列锨侯。主線程首先執(zhí)行同步任務(wù)嫩海,然后查看任務(wù)隊(duì)列是否有就緒的異步任務(wù)(或者時(shí)間到了的異步任務(wù)),調(diào)用相應(yīng)的回調(diào)函數(shù)執(zhí)行囚痴,直到任務(wù)隊(duì)列為空叁怪。至此即完成一個(gè)事件循環(huán)。
數(shù)組扁平化
將多層次的數(shù)組轉(zhuǎn)變成單層的數(shù)組
function flatten(arr) {
return arr.reduce(function (pre,item) {
return pre.concat(item instanceof Array?flatten(item):item)
},[])
}
.sort()
默認(rèn)按字典序排序深滚。如果要對數(shù)值排序:.sort(function(a,b){ return a-b })
獲取dom節(jié)點(diǎn)的兄弟節(jié)點(diǎn)
firstChild,lastChild,nextSibling,previousSibling都會將空格或者換行當(dāng)做節(jié)點(diǎn)處理奕谭,但是有代替屬性
所以為了準(zhǔn)確地找到相應(yīng)的元素,會用
firstElementChild,
lastElementChild,
nextElementSibling,
previousElementSibling
兼容的寫法痴荐,這是JavaScript自帶的屬性血柳。
但壞消息是IE6,7,8不兼容這些屬性。IE9以上和火狐谷歌支持生兆。
js實(shí)現(xiàn)二叉查找樹
function BinarySearchTree () {
? ? ? ? var Node = function(key) {
? ? ? ? ? ? this.key = key,
? ? ? ? ? ? this.left = null,
? ? ? ? ? ? this.right = null
? ? ? ? }
? ? ? ? var root = null
? ? ? ? //插入節(jié)點(diǎn)
? ? ? ? this.insert = function(key) {
? ? ? ? ? ? var newNode = new Node(key)
? ? ? ? ? ? if(root === null) {
? ? ? ? ? ? ? ? root = newNode
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? insertNode(root, newNode)
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? var insertNode = function(node, newNode) {
? ? ? ? ? ? if (newNode.key <= node.key) {
? ? ? ? ? ? ? ? if (node.left === null) {
? ? ? ? ? ? ? ? ? ? node.left = newNode
? ? ? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? ? ? insertNode(node.left, newNode)
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? if (node.right === null) {
? ? ? ? ? ? ? ? ? ? node.right = newNode
? ? ? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? ? ? insertNode(node.right, newNode)
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? //實(shí)現(xiàn)中序遍歷
? ? ? ? this.inOrderTraverse = function() {
? ? ? ? ? ? inOrderTraverseNode(root)
? ? ? ? }
? ? ? ? var inOrderTraverseNode = function(node) {
? ? ? ? ? ? if (node !== null) {
? ? ? ? ? ? ? ? inOrderTraverseNode(node.left)
? ? ? ? ? ? ? ? console.log(node.key)
? ? ? ? ? ? ? ? inOrderTraverseNode(node.right)
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? // 實(shí)現(xiàn)先序遍歷
? ? ? ? this.preOrderTraverse = function() {
? ? ? ? ? ? preOrderTraverseNode(root)
? ? ? ? }
? ? ? ? var preOrderTraverseNode = function(node) {
? ? ? ? ? ? if (node !== null) {
? ? ? ? ? ? ? ? console.log(node.key)
? ? ? ? ? ? ? ? preOrderTraverseNode(node.left)
? ? ? ? ? ? ? ? preOrderTraverseNode(node.right)
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? // 實(shí)現(xiàn)后序遍歷
? ? ? ? this.postOrderTraverse = function() {
? ? ? ? ? ? postOrderTraverseNode(root)
? ? ? ? }
? ? ? ? var postOrderTraverseNode = function(node) {
? ? ? ? ? ? if (node !== null) {
? ? ? ? ? ? ? ? postOrderTraverseNode(node.left)
? ? ? ? ? ? ? ? postOrderTraverseNode(node.right)
? ? ? ? ? ? ? ? console.log(node.key)
? ? ? ? ? ? }
? ? ? ? }
? ? }
Null和Undefined
var?oValue;
alert(oValue?==?undefined);//output?"true"??
這段代碼顯示為true,代表oVlaue的值即為undefined难捌,因?yàn)槲覀儧]有初始化它。
alert(null==?document.getElementById('notExistElement'));
當(dāng)頁面上不存在id為"notExistElement"的DOM節(jié)點(diǎn)時(shí)鸦难,這段代碼顯示為"true"根吁,因?yàn)槲覀儑L試獲取一個(gè)不存在的對象。
JS實(shí)現(xiàn)快速排序
大致分三步:
1合蔽、找基準(zhǔn)(一般是以中間項(xiàng)為基準(zhǔn))
2击敌、遍歷數(shù)組,小于基準(zhǔn)的放在left拴事,大于基準(zhǔn)的放在right
3沃斤、遞歸
function quickSort(arr){
? ? ? ? ? ? //如果數(shù)組<=1,則直接返回if(arr.length<=1){return arr;}
? ? ? ? ? ? var pivotIndex=Math.floor(arr.length/2);//找基準(zhǔn),并把基準(zhǔn)從原數(shù)組刪除varpivot=arr.splice(pivotIndex,1)[0];
? ? ? ? ? ? //定義左右數(shù)組va rleft=[];
? ? ? ? ? ? var right=[];
? ? ? ? ? ? //比基準(zhǔn)小的放在left刃宵,比基準(zhǔn)大的放在rightfor(vari=0;i
? ? ? ? ? ? ? ? if(arr[i]<=pivot){
? ? ? ? ? ? ? ? ? ? left.push(arr[i]);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else{
? ? ? ? ? ? ? ? ? ? right.push(arr[i]);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? //遞歸return quickSort(left).concat([pivot],quickSort(right));
? ? ? ? }? ? ? ? ? ? ? ?
js手動實(shí)現(xiàn)call轰枝,apply,bind
Function.prototype.myCall =function(obj, ...args){
//我們要讓傳入的obj成為, 函數(shù)調(diào)用時(shí)的this值.
obj._fn_ =this;//在obj上添加_fn_屬性组去,值是this(要調(diào)用此方法的那個(gè)函數(shù)對象)鞍陨。
obj._fn_(...args);//在obj上調(diào)用函數(shù),那函數(shù)的this值就是obj.
deleteobj._fn_;// 再刪除obj的_fn_屬性,去除影響.
//_fn_ 只是個(gè)屬性名 你可以隨意起名,但是要注意可能會覆蓋obj上本來就有的屬性
}
Function.prototype.myApply =function(obj, ...args){
//我們要讓傳入的obj成為, 函數(shù)調(diào)用時(shí)的this值.
obj._fn_ =this;//在obj上添加_fn_屬性,值是this(要調(diào)用此方法的那個(gè)函數(shù)對象)诚撵。
obj._fn_(args);//在obj上調(diào)用函數(shù),那函數(shù)的this值就是obj.
deleteobj._fn_;// 再刪除obj的_fn_屬性,去除影響.
//_fn_ 只是個(gè)屬性名 你可以隨意起名缭裆,但是要注意可能會覆蓋obj上本來就有的屬性
}
Function.prototype.es6Bind = function(context, ...rest) {
? if (typeof this !== 'function') throw new TypeError('invalid invoked!');
? var self = this;
? return function F(...args) {
? ? if (this instanceof F) {
? ? ? return new self(...rest, ...args)
? ? }
? ? return self.apply(context, rest.concat(args))
? }
}
new的簡單實(shí)現(xiàn)
function newFunc(constructor){
? ? ? //第一步:創(chuàng)建一個(gè)空對象obj
? ? ? ? var obj = {};
? ? ? //第二步:將構(gòu)造函數(shù) constructor的原型對象賦給obj的原型
? ? ? ? obj.__proto__ = constructor.prototype;
? ? ? //第三步:將構(gòu)造函數(shù) constructor中的this指向obj,并立即執(zhí)行構(gòu)造函數(shù)內(nèi)部的操作
? ? ? ? constructor.apply(obj);
? ? ? //第四步:返回這個(gè)對象
? ? ? ? return obj;
}
保留小數(shù)
varnum =2.446242342;
num = num.toFixed(2); // 輸出結(jié)果為 2.45
let、const寿烟、var 的區(qū)別
是否存在變量提升澈驼?
var聲明的變量存在變量提升(將變量提升到當(dāng)前作用域的頂部)。即變量可以在聲明之前調(diào)用筛武,值為undefined缝其。
let和const不存在變量提升。即它們所聲明的變量一定要在聲明后使用徘六,否則報(bào)ReferenceError錯内边。
是否存在暫時(shí)性死區(qū)
let和const存在暫時(shí)性死區(qū)。即只要塊級作用域內(nèi)存在let命令待锈,它所聲明的變量就“綁定”(binding)這個(gè)區(qū)域漠其,不再受外部的影響。
是否允許重復(fù)聲明變量
var允許重復(fù)聲明變量竿音。let和const在同一作用域不允許重復(fù)聲明變量和屎。
是否存在塊級作用域
var不存在塊級作用域(內(nèi)層變量可能會覆蓋外層變量,計(jì)數(shù)的循環(huán)變量泄露為全局變量)春瞬。let和const存在塊級作用域柴信。
是否能修改聲明的變量
var和let可以。const聲明一個(gè)只讀的常量宽气。
DOM事件流
即比如點(diǎn)擊td元素時(shí)颠印,由外至內(nèi)層會經(jīng)歷捕獲階段,目標(biāo)階段抹竹,冒泡階段三個(gè)階段线罕,相應(yīng)地會觸發(fā)路徑元素上的事件?
此外,addEventListener(type, listener[, useCapture])函數(shù)默認(rèn)設(shè)置在冒泡階段窃判。
事件委托
在父元素上監(jiān)聽事件钞楼;通過event.target確定觸發(fā)源。
substring和substr的區(qū)別
兩者都是截取字符串袄琳。
相同點(diǎn):如果只是寫一個(gè)參數(shù)询件,兩者的作用都一樣:都是是截取字符串從當(dāng)前下標(biāo)以后直到字符串最后的字符串片段。
substr(startIndex);
substring(startIndex);
不同點(diǎn):第二個(gè)參數(shù)
substr(startIndex,lenth): 第二個(gè)參數(shù)是截取字符串的長度(從起始點(diǎn)截取某個(gè)長度的字符串)唆樊;
substring(startIndex, endIndex): 第二個(gè)參數(shù)是截取字符串最終的下標(biāo) (截取2個(gè)位置之間的字符串,‘含頭不含尾’)宛琅。
window對象
子對象:
navigator對象(了解即可)
瀏覽器對象,通過這個(gè)對象可以判定用戶所使用的瀏覽器逗旁,包含了瀏覽器相關(guān)信息嘿辟。
?screen對象(了解即可)
屏幕對象舆瘪,不常用。
history對象(了解即可)
window.history 對象包含瀏覽器的歷史红伦。
location對象
window.location 對象用于獲得當(dāng)前頁面的地址 (URL)英古,并把瀏覽器重定向到新的頁面。
localstorage和sessionstorage
前端路由
前端路由的兩種模式: hash 模式和 history 模式
hash模式
這里的 hash 就是指 url 尾巴后的 # 號以及后面的字符昙读。這里的 # 和 css 里的 # 是一個(gè)意思召调。hash 也 稱作 錨點(diǎn),本身是用來做頁面定位的蛮浑,她可以使對應(yīng) id 的元素顯示在可視區(qū)域內(nèi)唠叛。
由于 hash 值變化不會導(dǎo)致瀏覽器向服務(wù)器發(fā)出請求,而且 hash 改變會觸發(fā) hashchange 事件沮稚,瀏覽器的進(jìn)后退也能對其進(jìn)行控制艺沼,所以人們在 html5 的 history 出現(xiàn)前,基本都是使用 hash 來實(shí)現(xiàn)前端路由的壮虫。
使用到的api:
window.location.hash ='qq'// 設(shè)置 url 的 hash澳厢,會在當(dāng)前url后加上 '#qq'
varhash =window.location.hash// '#qq'??
window.addEventListener('hashchange',function(){// 監(jiān)聽hash變化环础,點(diǎn)擊瀏覽器的前進(jìn)后退會觸發(fā)})
history模式
已經(jīng)有 hash 模式了囚似,而且 hash 能兼容到IE8, history 只能兼容到 IE10线得,為什么還要搞個(gè) history 呢饶唤?
首先,hash 本來是拿來做頁面定位的贯钩,如果拿來做路由的話募狂,原來的錨點(diǎn)功能就不能用了。其次角雷,hash 的傳參是基于 url 的祸穷,如果要傳遞復(fù)雜的數(shù)據(jù),會有體積的限制勺三,而 history 模式不僅可以在url里放參數(shù)雷滚,還可以將數(shù)據(jù)存放在一個(gè)特定的對象中。
相關(guān)API:
window.history.pushState(state, title, url)// state:需要保存的數(shù)據(jù)吗坚,這個(gè)數(shù)據(jù)在觸發(fā)popstate事件時(shí)祈远,可以在event.state里獲取// title:標(biāo)題,基本沒用商源,一般傳 null// url:設(shè)定新的歷史記錄的 url车份。新的 url 與當(dāng)前 url 的 origin 必須是一樣的,否則會拋出錯誤牡彻。url可以是絕對路徑扎附,也可以是相對路徑怀酷。//如 當(dāng)前url是 https://www.baidu.com/a/,執(zhí)行history.pushState(null, null, './qq/')蚌成,則變成 https://www.baidu.com/a/qq/配喳,//執(zhí)行history.pushState(null, null, '/qq/'),則變成 https://www.baidu.com/qq/
window.history.replaceState(state, title, url)// 與 pushState 基本相同囱桨,但她是修改當(dāng)前歷史記錄,而 pushState 是創(chuàng)建新的歷史記錄
window.addEventListener("popstate",function(){// 監(jiān)聽瀏覽器前進(jìn)后退事件,pushState 與 replaceState 方法不會觸發(fā)? ? ? ? ? ? ? });
window.history.back()// 后退
window.history.forward()// 前進(jìn)
window.history.go(1)// 前進(jìn)一步盈蛮,-2為后退兩步,window.history.lengthk可以查看當(dāng)前歷史堆棧中頁面的數(shù)量
history 模式改變 url 的方式會導(dǎo)致瀏覽器向服務(wù)器發(fā)送請求技矮,這不是我們想看到的抖誉,我們需要在服務(wù)器端做處理:如果匹配不到任何靜態(tài)資源,則應(yīng)該始終返回同一個(gè) html 頁面衰倦。
用發(fā)布訂閱監(jiān)聽pushstate和replacestate
class Dep{
constructor(name){
this.id =new Date()
this.subs = []
}
defined(){
this.subs.push(Dep.watch)
}
notify(){
this.subs.forEach(item=>{
item.update()
})
}
}
Dep.watch =null
class watcher{
constructor(name,fn){
this.name =name
this.callback = fn
}
update(){
this.callback()
}
}
var addHistoryMethod = (function (){
var mydep =new Dep()
return function (name) {
if(name =='historychange'){
return function (name,fn) {
var watch =new watcher(name,fn)
Dep.watch = watch
mydep.defined()
Dep.watch =null
? ? ? }
}
else if(name ==='pushState' || name ==='replaceState'){
var method = history[name];
? ? ? return function(){
method.apply(history, arguments);
? ? ? ? mydep.notify()
}
}
}
}())
window.addHistoryListener = addHistoryMethod('historychange');
history.pushState =? addHistoryMethod('pushState');
history.replaceState =? addHistoryMethod('replaceState');
window.addHistoryListener('history',function(){
console.log('窗口的history改變了');
})
window.addHistoryListener('history',function(){
console.log('窗口的history改變了-我也聽到了');
})
history.pushState({first:'first'}, "page2", "/first")
獲得table里的行或列
var table = document.getElementById('mytable')
var tr = table.getElementsByTagName('tr')
js ascall碼轉(zhuǎn)換
str="A";
code = str.charCodeAt();//65
str2 = String.fromCharCode(code);//A
str3 = String.fromCharCode(0x60+26);//Z
添加或刪除類名
添加:節(jié)點(diǎn).classList.add("類名")袒炉;
刪除:節(jié)點(diǎn).classList.remove("類名");
js中判斷數(shù)組中是否包含某元素的方法
方法一:arr.indexOf(某元素):未找到則返回 -1樊零。
arr.includes()? ?數(shù)組中含有某值返回true我磁,沒有返回false
event.x和event.clientX和event.offsetX
event.x和event.clientX為相對與窗口的位置。
event.offsetX為相對于目標(biāo)對象的padding外邊緣的位置驻襟,如果點(diǎn)擊在border中的話夺艰,會取到負(fù)值
.concat()合并數(shù)組不會改變原數(shù)組,而是返回一個(gè)新數(shù)組
JS深拷貝
function deepCopy(obj) {
? ? ? varresult = Array.isArray(obj) ? [] : {};
? ? ? for(var key in obj) {
? ? ? ? if (obj.hasOwnProperty(key)) {
? ? ? ? ? if(typeofobj[key] ==='object' && obj[key]!==null) {
? ? ? ? ? ? result[key] = deepCopy(obj[key]);? //遞歸復(fù)制
? ? ? ? ? } else {
? ? ? ? ? ? result[key] = obj[key];
? ? ? ? ? }
? ? ? ? }
? ? ? }
? ? ? return result;
? ? }
js堆排序
// 交換兩個(gè)節(jié)點(diǎn)
function swap(A, i, j) {
? let temp = A[i];
? A[i] = A[j];
? A[j] = temp;
}
// 將 i 結(jié)點(diǎn)以下的堆整理為大頂堆沉衣,注意這一步實(shí)現(xiàn)的基礎(chǔ)實(shí)際上是:
// 假設(shè) 結(jié)點(diǎn) i 以下的子堆已經(jīng)是一個(gè)大頂堆郁副,shiftDown函數(shù)實(shí)現(xiàn)的
// 功能是實(shí)際上是:找到 結(jié)點(diǎn) i 在包括結(jié)點(diǎn) i 的堆中的正確位置。后面
// 將寫一個(gè) for 循環(huán)豌习,從第一個(gè)非葉子結(jié)點(diǎn)開始存谎,對每一個(gè)非葉子結(jié)點(diǎn)
// 都執(zhí)行 shiftDown操作,所以就滿足了結(jié)點(diǎn) i 以下的子堆已經(jīng)是一大
//頂堆
function shiftDown(A, i, length) {
? let temp = A[i]; // 當(dāng)前父節(jié)點(diǎn)
// j<length 的目的是對結(jié)點(diǎn) i 以下的結(jié)點(diǎn)全部做順序調(diào)整
? for(let j = 2*i+1; j<length; j = 2*j+1) {
? ? temp = A[i];? // 將 A[i] 取出肥隆,整個(gè)過程相當(dāng)于找到 A[i] 應(yīng)處于的位置
? ? if(j+1 < length && A[j] < A[j+1]) {
? ? ? j++;? // 找到兩個(gè)孩子中較大的一個(gè)既荚,再與父節(jié)點(diǎn)比較
? ? }
? ? if(temp < A[j]) {
? ? ? swap(A, i, j) // 如果父節(jié)點(diǎn)小于子節(jié)點(diǎn):交換;否則跳出
? ? ? i = j;? // 交換后栋艳,temp 的下標(biāo)變?yōu)?j
? ? } else {
? ? ? break;
? ? }
? }
}
// 堆排序
function heapSort(A) {
? // 初始化大頂堆恰聘,從第一個(gè)非葉子結(jié)點(diǎn)開始
? for(let i = Math.floor(A.length/2-1); i>=0; i--) {
? ? shiftDown(A, i, A.length);
? }
? // 排序,每一次for循環(huán)找出一個(gè)當(dāng)前最大值嘱巾,數(shù)組長度減一
? for(let i = Math.floor(A.length-1); i>0; i--) {
? ? swap(A, 0, i); // 根節(jié)點(diǎn)與最后一個(gè)節(jié)點(diǎn)交換
? ? shiftDown(A, 0, i); // 從根節(jié)點(diǎn)開始調(diào)整憨琳,并且最后一個(gè)結(jié)點(diǎn)已經(jīng)為當(dāng)
? ? ? ? ? ? ? ? ? ? ? ? // 前最大值,不需要再參與比較旬昭,所以第三個(gè)參數(shù)
? ? ? ? ? ? ? ? ? ? ? ? // 為 i篙螟,即比較到最后一個(gè)結(jié)點(diǎn)前一個(gè)即可
? }
}
let Arr = [4, 6, 8, 5, 9, 1, 2, 5, 3, 2];
heapSort(Arr);
alert(Arr);
希爾排序(增量排序)
//shellSort
function shellSort(arr) {
? for(let gap = Math.floor(arr.length/2); gap > 0; gap = Math.floor(gap/2)) {
??? // 內(nèi)層循環(huán)與插入排序的寫法基本一致,只是每次移動的步長變?yōu)?gap
??? for(let i = gap; i < arr.length;
i++) {
????? let j =i;
????? let temp =arr[j];
????? for(; j> 0; j -=gap) {
??????? if(temp >= arr[j-gap]) {
????????? break;
??????? }
??????? arr[j]= arr[j-gap];
????? }
????? arr[j]=temp;
??? }
? }
? return arr;
}
// example
let arr = [2,5,10,7,10,32,90,9,11,1,0,10];
alert(shellSort(arr));
判斷dom節(jié)點(diǎn)的是否包含某個(gè)子節(jié)點(diǎn)
contains?自帶方法问拘,判斷一個(gè)元是不是另一個(gè)元的子集
document.documentElement.contains(document.body)
數(shù)組深拷貝
1.var arr = arr2.concat()
2.var arr = arr2.map(item=>return item)
JS-設(shè)計(jì)模式
工廠模式
工廠函數(shù)就是做一個(gè)對象創(chuàng)建的封裝遍略,并將創(chuàng)建的對象return出去
?function newObj(name,age){
??? var o = new Object();
??? o.name=name;
??? o.age=age;
??? returno;
}
var obj = newObj();
單例模式:只允許存在一個(gè)實(shí)例的模式
?var Instance = (function(){
??? varobj;
??? return function(){
??????? if(obj === undefined) obj = new Date();
??????? returnobj;
??? }
})();
var ibs = Instance();
觀察者模式
又稱發(fā)布訂閱者模式惧所,經(jīng)典案例:事件監(jiān)聽,一個(gè)元素同時(shí)監(jiān)聽多個(gè)同類型事件绪杏,元素對象即為發(fā)布者下愈,每一個(gè)事件處理函數(shù)即為訂閱者。
策略模式
策略模式的定義是:定義一系列的算法蕾久,把它們一個(gè)個(gè)封裝起來势似,并且使它們可以相互替換,從而避免很多if語句僧著,曾經(jīng)學(xué)過最簡單的策略模式雛形就是使用數(shù)組的方式解決傳入數(shù)字得到對應(yīng)星期幾問題的算法履因。
比如公司的年終獎是根據(jù)員工的工資和績效來考核的,績效為A的人盹愚,年終獎為工資的4倍栅迄,績效為B的人,年終獎為工資的3倍皆怕,績效為C的人毅舆,年終獎為工資的2倍
?var obj ={
??? "A": function(salary) {
??????? return salary * 4;
??? },
??? "B" : function(salary) {
??????? return salary * 3;
??? },
??? "C" : function(salary) {
??????? return salary * 2;
??? }
};
var calculateBouns =function(level,salary){
??? returnobj[level](salary);
};
console.log(calculateBouns('A',10000)); // 40000
代理模式
代理模式(Proxy),為其他對象提供一種代理以控制對這個(gè)對象的訪問愈腾,為了不暴露執(zhí)行對象的部分代碼
?//三個(gè)對象
//用戶委托快捷方式打開exe
//為了不暴露執(zhí)行對象的部分代碼
//男孩委托快遞小哥給女孩送禮物
var girl = function(name){
??? this.name =name;
}
//隱藏復(fù)雜憋活,不愿意修改的的方法
var boy = function(girl){
??? this.girl =girl;
??? this.send = function(gift){
??????? alert("你好:"+this.girl.name+",給你一個(gè)"+gift);
??? }
}
var proxyBro = function(girl){
??? this.send = function(gift){
??????? new boy(girl).send(gift);
??? }
}
var pro = new proxyBro(new girl("Lisa"));
pro.send("么么噠");
pro.send("玫瑰花");
模塊模式:
在立即執(zhí)行函數(shù)表達(dá)式中定義的變量和方法在外界是訪問不到的,只能通過其向外部提供的接口,"有限制"地訪問.通過函數(shù)作用域解決了屬性和方法的封裝問題.
var?Person = (function(){
??var?name =?"xin";
??var?age = 22;
??function?getName(){
????return?name;
??}
??function?getAge(){
????return?age;
??}
??return?{
????getName: getName,
????getAge: getAge
??}
})();
console.log(age);?// 報(bào)錯:age未定義
console.log(name);?// 報(bào)錯:name未定義
console.log(Person.age);?// undefined
console.log(Person.name);?// undefined
// 只能通過Person提供的接口訪問相應(yīng)的變量
console.log(Person.getName());?// xin
console.log(Person.getAge());?// 22
構(gòu)造函數(shù)模式
混合模式
function?Person(name,age){
??this.name = name;
??this.age = age;
};
Person.prototype.printName =?function(){
??console.log(this.name);
}
function?Student(name,age){
??// 繼承 Person 的屬性
??Person.call(this,name,age);
}
function?create(prototype){
??function?F(){};
??F.prototype = prototype;
??return?new?F();
}
// 讓Student的原型指向一個(gè)對象,該對象的原型指向了Person.prototype,通過這種方式繼承 Person 的方法
Student.prototype = create(Person.prototype);
Student.prototype.printAge =?function(){
??console.log(this.age);
}
var?student =?new?Student('xin',22);
student.printName();?// "xin"
進(jìn)制轉(zhuǎn)換
parseInt(num,8); //八進(jìn)制轉(zhuǎn)十進(jìn)制
parseInt(num,16);? //十六進(jìn)制轉(zhuǎn)十進(jìn)制
parseInt(num).toString(8)//十進(jìn)制轉(zhuǎn)八進(jìn)制
parseInt(num).toString(16)//十進(jìn)制轉(zhuǎn)十六進(jìn)制
parseInt(num,2).toString(8)//二進(jìn)制轉(zhuǎn)八進(jìn)制
parseInt(num,2).toString(16)//二進(jìn)制轉(zhuǎn)十六進(jìn)制
parseInt(num,8).toString(2)//八進(jìn)制轉(zhuǎn)二進(jìn)制
parseInt(num,8).toString(16)//八進(jìn)制轉(zhuǎn)十六進(jìn)制
parseInt(num,16).toString(2)//十六進(jìn)制轉(zhuǎn)二進(jìn)制
parseInt(num,16).toString(8)//十六進(jìn)制轉(zhuǎn)八進(jìn)制