首次查詢的時候緩存結果。這樣狀況就變得簡單了,不管是結果條目的數量,總共的頁面數量,仍是取出其中的部分條目。javascript
不顯示總共有多少條目。Google搜索結果的分頁顯示就用了這個特性。不少時候你可能看了前幾頁,就夠了。那麼我能夠這樣,每次我都把結果限制在500條(這個數據越大 資源消耗越大)而後你每次查詢的時候,都查詢501條記錄,這樣,若是結果然有501個,那麼咱們就顯示連接 「顯示下500條記錄」。html
不顯示總頁面數。只給出「下一頁」的連接,若是有下一頁的話。(若是用戶想看上一頁的話,他會經過瀏覽器來回到上一頁的)。那你可能會問我「不顯示總頁面數」怎麼知道是否是有下一頁呢?這裏有一個很好的小技巧:你在每次顯示你當前頁面條目的時候你都多查詢一條,例如你要顯示第11-20個條目時,你就取出11-21條記錄(多取一條,並不顯示這多取的內容),那麼當你發現第21條存在的時候就顯示「下一頁的連接」,不然就是末頁了。這樣你就不用每次計算總頁面數量了,特別是在作緩存很困難的時候這樣作效率很是好。java
估算總結果數。Google就是這麼作的,事實證實效果很好。用EXPLAIN 來解釋你的SQL,而後經過EXPLAIN的結果來估算。EXPLAIN結果有一列」row」會給你一個大概的結果。(這個辦法不是到處都行,可是某些地方效果是很好的)這些辦法能夠很大程度上減輕數據庫的壓力,並且對用戶體驗不會有什麼影響。web
爲何script標籤引入的文件不受同源策略的限制?由於script標籤引入的文件內容是不可以被客戶端的js獲取到的,不會影響到被引用文件的安全,因此不必使script標籤引入的文件遵循瀏覽器的同源策略。而經過ajax加載的文件內容是可以被客戶端js獲取到的,因此ajax必須遵循同源策略,不然被引入文件的內容會泄漏或者存在其餘風險ajax
function loadScript(url, func) { var head = document.head || document.getElementByTagName('head')[0]; var script = document.createElement('script'); script.src = url; script.onload = script.onreadystatechange = function() { if(!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') { func(); script.onload = script.onreadystatechange = null; } }; head.appendChild(script); } window.baidu = { sug: function(data) { console.log(data); } } loadScript('http://suggestion.baidu.com/su?wd=w', function() { console.log('loaded') }); //此處能夠是服務端的數據接口直接返回須要的信息 // loadScript('http://localhost:8080/resteasyDemo/rest/echo/test?test=1', function() { // console.log('loaded') // console.log(name) // });
window.name 的美妙之處:name 值在不一樣的頁面(甚至不一樣域名)加載後依舊存在,而且能夠支持很是長的 name 值(2MB)。數據庫
步驟 1 建立包含獲取和建立iframe代碼的A域名下a.htmljson
步驟 2 建立A域名下的空頁面b.html跨域
目的是當iframe設置跨域後的頁面後當即從新src到同源的b.html頁面,從而完成加載的是跨域頁面而實際src是同源頁面,用來實現同源獲取值promise
a.html頁面寫以下代碼瀏覽器
function proxy(url, func) { var isFirst = true, ifr = document.createElement('iframe'), loadFunc = function() { if(isFirst) { ifr.contentWindow.location = 'http://10.149.4.6:8020/b.html'; isFirst = false; } else { func(ifr.contentWindow.name); ifr.contentWindow.close(); document.body.removeChild(ifr); ifr.src = ''; ifr = null; } }; ifr.src = url; ifr.style.display = 'none'; if(ifr.attachEvent) ifr.attachEvent('onload', loadFunc); else ifr.onload = loadFunc; document.body.appendChild(ifr); }
調用跨域頁面
proxy('http://10.149.4.10:8080/c.html', function(data) { console.log(JSON.stringify(data)); });
c頁面設置window.name
<body> <script type="text/javascript"> window.name='{"foo":"bar"}'; </script> </body>
a.com/index.html
<iframe id="ifr" src="b.com/index.html"></iframe> <script type="text/javascript"> window.onload = function() { var ifr = document.getElementById('ifr'); var targetOrigin = 'http://b.com'; // 若寫成'http://b.com/c/proxy.html'效果同樣 // 若寫成'http://c.com'就不會執行postMessage了 ifr.contentWindow.postMessage('I was there!', targetOrigin); }; </script>
b.com/index.html
<script type="text/javascript"> window.addEventListener('message', function(event){ // 經過origin屬性判斷消息來源地址 if (event.origin == 'http://a.com') { alert(event.data); // 彈出"I was there!" alert(event.source); // 對a.com、index.html中window對象的引用 // 但因爲同源策略,這裏event.source不能夠訪問window對象 } }, false); </script>
不用多說..js標籤執行回調
var socket = new WebSockt('ws://www.baidu.com');//http->ws; https->wss socket.send('hello WebSockt'); socket.onmessage = function(event){ var data = event.data; }
須要瞭解的是 對象的 冒泡事件和捕獲事件(true)
1 針對同一個元素來講捕獲事件和冒泡事件的執行順序取決於對這個元素綁定事件的前後聲明
2 對於除去自己點擊元素外的父元素來講,捕獲事件優先於冒泡事件觸發
e.target和e.currentTarget區別是 前者是事件觸發的元素,後者是事件綁定的觸發元素
對淺拷貝的一次遞歸實現了深拷貝
function cloneOriginal(obj) { if(typeof obj != "object" && obj != null || obj == null) return obj; var temObj = obj.constructor === Array?[]:{}; for(var key in obj) { temObj[key] = cloneOriginal(obj[key]); } return temObj; } function extend() { if(arguments.length < 2) return arguments; var temObj = cloneOriginal(arguments[0]); for(var i = 1;i<arguments.length;i++) { for(var j in arguments[i]) { temObj[j] = cloneOriginal(arguments[i][j]); } } return temObj; } var a = {name:111,age:222,kkk:[1,2,3],ddd:{height:100},e:function() {console.log("eee")}}; var b = {width:333}; var c = {color:"黃色",border:"1px"}; var d = extend(b,a,c); console.log(d); a.kkk.push(44444); console.log(d); //2使用json解析 var a2 = {name:111,age:222,kkk:[1,2,3],ddd:{height:100}}; var b2 = JSON.parse(JSON.stringify(a)); console.log(b2); }
而其中json解析的方法對於序列化的簡單的拷貝來講能夠,可是對於很大沒有徹底序列化的對象來講是不行的
例:var a = {name:111,b:function() {}}
上圖中,主線程運行的時候,產生堆(heap)和棧(stack),棧中的代碼調用各類外部API,它們在"任務隊列"中加入各類事件(click,load,done)。只要棧中的代碼執行完畢,主線程就會去讀取"任務隊列",依次執行那些事件所對應的回調函數。
執行棧中的代碼(同步任務),老是在讀取"任務隊列"(異步任務)以前執行
當頁面動畫很是繁多,而且須要不斷的刷新不一樣動畫數據的時候,瀏覽器每次收到從Server端發來的消息,js腳本都會將消息的內容做爲一個新的文本節點添加到頁面中去。這樣作,會馬上致使HTML文檔的部分DOM樹重構,部分渲染樹重構,部分渲染樹重排,已經部分渲染樹重繪。也就是說,每當瀏覽器收到一條消息,都會執行上面的4個步驟。這樣一來,處理每條消息時,瀏覽器畫在更新渲染頁面上的時間大大超出了js腳本運行所需的時間。因而咱們看到的結果就是頁面變得很是卡,用戶體驗極差。
經過setTimeout遞歸調用本身,而且是每隔16ms調用一次,大約一秒60次。每次被調用的時候,該函數都會挨個檢查頁
偏函數應用 閉包應用的一種
實例:
function joinWords(a,b) { return [a,b].join(' '); } function prefixer(word) { return function(b) { return joinWords(word,b); } } var prefixWithHate = prefixer('Hate'); console.log(prefixWithHat('Java'));
prefixer函數授受一個詞做爲參數,返回一個函數並預先填入這個詞做爲第一個參數,這是利用閉包,word 對於內部函數是能夠訪問的,
學習點,
偏函數中的閉包 參數對於子函數永遠可見
函數內用retrurn 返回函數的寫法
用一個變量得到成爲一個函數,
偏函數設置默認的是值,並不變量,相似閉包實現
ECMAScript 中,全部函數的參數都是按值來傳遞的。基本類型值的傳遞和基本類型變量複製一致(採用在棧內新建值),引用類型值的傳遞和引用類型變量的複製一致(棧內存空間的複製,棧內存放的是指針,指向堆中同一對象
Function.prototype.bind_ = function() { var t = this, param = Array.prototype.slice.call(arguments), fn = param.shift(), content = param; return function() { return t.apply(fn, content.concat(Array.prototype.slice.call(arguments))); } } //賦值默認值 var fuzhi = function() { var t = this, param = Array.prototype.slice.call(arguments), fn = param.shift(), content = param; return function() { return fn.apply(this,content.concat(Array.prototype.slice.call(arguments))) } } function test(n,name) { setTimeout(function() { console.log(name); },n) } var test_ = fuzhi(test,2000); test_("hahah"); }
這是在書中看到的,拿來總結下
當一個函數對象被建立時,Function構造器產生的函數對象會運行這樣的一段代碼:
Function.prototype = {constructor:this}
new的實際意義:
Function.prototype.method = function(name,fn) { if(this.prototype[name]) return this; this.prototype[name] = fn; return this; } Function.method('new',function() { var that = Object.create(this.prototype); var other = this.apply(that,arguments); return (typeof other === 'object' && other) || that; }) }
簡單應用例子
//簡單的僞類繼承 Function.method("jc",function(jcObj) { this.prototype = new jcObj(); return this; }) var people = function() { this.name = "people"; }.method("getName",function() { console.log(this.name); }) var man = function() { this.manName = "man"; } .jc(people) .method("detail",function() { console.log("my father`s name is: "+this.name); console.log("my name is: "+this.manName); }) var obj = new man(); obj.detail() }
實際簡單總結下就是以下代碼
step1 :建立構造函數
function A() { this.name = "a"; } var a = new A();
step2 建立a實例使用new經歷瞭如下四個步驟
1 var obj = {};
2 obj.__proto__ = A.prototype;
3 A.call(obj);
4 return obj;