##js的拖拽javascript
在拖拽時容易使操做變成選擇文本,這時應該添加這段:html
$("#ul").on("selectstart", "li", function(e){ this.dragDrop && this.dragDrop(); return false; });
##js的event對象前端
先看文章的代碼:java
//獲取event對象 //標準DOM方法事件處理函數第一個參數是event對象 //IE可使用全局變量window.event var evt = window.event?window.event:e; //獲取觸發事件的原始事件源 //標準DOM方法是用target獲取當前事件源 //IE使用evt.srcElement獲取事件源 var target = evt.target||evt.srcElement; //獲取當前正在處理的事件源 //標準DOM方法是用currentTarget獲取當前事件源 //IE中的this指向當前處理的事件源 var currentTarget= e?e.currentTarget:this; //問題:在IE 9下 window.event 與 e 不一樣 evt沒有currentTarget屬性,e纔有currentTarget屬性(視爲標準瀏覽器作法??) alert("src id:"+target.id+"\ncurent target id :"+currentTarget.id);
currentTarget:事件冒泡階段所在的DOM。在捕獲事件時,這個currentTarget就爲監聽事件的那個DOM元素,當事件結束時,currentTarget爲nulljquery
target, originalTarget, srcElement:觸發事件原始的DOMgit
##jQuery.ready, DOMContentLoaded, window.onload區別github
先看jQuery.ready,查看jquery-1.11.3.js
源代碼:ajax
// Catch cases where $(document).ready() is called after the browser event has already occurred. // we once tried to use readyState "interactive" here, but it caused issues like the one // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready setTimeout( jQuery.ready ); // Standards-based browsers support DOMContentLoaded } else if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", completed, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", completed, false ); // If IE event model is used } else { // Ensure firing before onload, maybe late but safe also for iframes document.attachEvent( "onreadystatechange", completed ); // A fallback to window.onload, that will always work window.attachEvent( "onload", completed ); ......
可看出jQuery也是主要利用DOMContentLoaded事件編程
DOMContentLoaded是在DOM結構繪製完畢後就執行,不必定要等全部的js和圖片加載完畢,就能夠執行一些方法json
window.onload則必須等到頁面內包括圖片(圖片也加載完成,img.complete===true時)的全部元素加載完畢後才能執行
##javascript三種設置訪問器屬性的方式
詳情:http://avalonjs.github.io/#tutorial/concepts/vmodel.html
另外一小小的知識點:普通類型變量給它定義屬性沒用
##針對retina的支持
// 優化retina, 在retina下這個值是2 var ratio = window.devicePixelRatio || 1;
##判斷圖片是否已加載了
利用complete
屬性可判斷:img.complete
##運算符的優先級
##visibilitychange事件
標籤頁激活檢測(視覺改變觸發):當用戶焦點在另一個標籤上,或從新回到標籤時,觸發visibilitychange
事件:
$(document).on('visibilitychange', function (e) { if (e.target.visibilityState === "visible") { console.log('Tab is now in view!'); } else if (e.target.visibilityState === "hidden") { console.log('Tab is now hidden!'); } });
##cookies,sessionStorage和localStorage的區別
x = 1 function bar(){ this.x = 2 return x } var foo = new bar() alert(foo.x) // -> 2
這裏主要問題是最外面x的定義,試試把x=1改爲x={},結果會不一樣的。這是爲何呢?
在把函數看成構造器使用的時候,若是手動返回了一個值,要看這個值是否簡單類型,若是是,等同於不寫返回,若是不是簡單類型,獲得的就是手動返回的值。若是,不手動寫返回值,就會默認從原型建立一個對象用於返回。
##js的script標籤的defer和async屬性
[defer]
能夠在<script>
中加入defer
屬性,告訴瀏覽器這段script沒必要當即執行,那麼瀏覽器就會在徹底載入文檔以後再執行這個script,至關於window.onload
,但它比window.onload
更靈活。
<script defer="true"></script>
[async]
使用async
屬性加載JavaScript,這樣整個腳本就能夠異步加載和執行。
<script>
標籤的defer屬性——告訴瀏覽器該腳本不會在頁面加載完成以前操做DOM,腳本將會和其餘資源文件並行下載; <script>
標籤的async屬性——HTML5新的異步、並行模式,腳本將在完成下載後等待合適的時機執行代碼。
##parseInt,parseFloat
parseInt('0xA') // return 10` parseInt('A') // return NaN` parseInt('A', 16) // return 10` parseFloat('22.22.22') // return 22.22` parseFloat('A', 16) // return NaN`,沒有基模式 parseFloat('0xA') // return 0`,不轉換爲十六進制,直接轉前面數字部分而已
void
運算符對任何值都返回undefined
,該運算符經常使用於避免輸出不該該輸出的值。例如: <a href="javascript:window.open('about:blank');">Click Me</a>
其中,window.open()
返回對新打開窗口的引用,會輸出字符串的,應該改成: <a href="javascript:void(window.open('about:blank'));">Click Me</a>
==
false == 0 -> true false == "0" -> true null == 0 -> false +null === 0 -> true null <= 0 -> true null < 1 -> true '' == 0 -> true // ''會被轉換爲數字, 至關於+'' == 0 '' == false -> true [] == false -> true [] == '' -> true true == 1 -> true true == 2 -> false '5' == 5 -> true isNaN('123') -> false isNaN(null) -> false Number([]) === Number('') === 0
小結:null 只弱等於 undefined , 但Number(null)等於0,0跟false是弱等的,因此 null != false, +null == false
使用scriptCharset
便可解決問題,用contentType
就不必定能夠了。
$.ajax({ url: testUrl, dataType: 'jsonp', type: 'post', scriptCharset: 'utf-8' });
##URL的基本概念:URL完整組成部分
糾正一下:
path
參數不包括hash
window.location
不包括path屬性,只有pathname##window.onload和DOMContentLoaded事件的區別
前者是DOM,圖片,樣式表,flash等加載完成後觸發的,後者是DOM加載完成,但樣式表和圖片可能未加載完成時就觸發的,而且只在某些瀏覽器中有此事件。
##JavaScript的原型
JavaScript是基於原型的編程語言,當你讀取一個對象的屬性,JavaScript首先會在本地對象中查找這個屬性,若是沒找到,JavaScript開始在對象的原型中查找,若仍未找到,還會繼續查找原型的原型,直到查找到Object.prototype。若是找到這個屬性,則返回這個值,不然返回undefined. 換句話說,若是你給Array.prototype添加了屬性,那麼全部JavaScript數組都具備了這個屬性
##變量提高
變量提高指的是,不管是哪裏的變量,都是在一個範圍內聲明的。JavaScript引擎會將這個聲明移到範圍的頂部。如:
function foo(){ // 此處省略若干代碼 var a = 100; }
運行代碼時,實質就是這樣:
function foo(){ var a; // 此處省略若干代碼 a = 100; }
##hasOwnProperty ##isPrototypeOf ##constructor
hasOwnProperty
檢查該對象是否有屬於它自己的屬性/對象,而不是它原型上的屬性/對象。由於畢竟那是它原型的屬性,而不是它本身的。就等於你能夠花你老爸的錢,但畢竟不是你的錢。如:
isPrototypeOf
顧名思義,檢查該對象是否爲另一對象的原型
constructor
對建立對象的函數的引用(指針),指向的老是一個function
prototype
對該對象原型的引用,返回的是一個object實例
var Foo = function(){ this.age = 25; }; Foo.prototype.count = 100; Foo.prototype.get = function(){return this.count;}; var f = new Foo(); console.log("age",f.hasOwnProperty("age")); // age true console.log("count",f.hasOwnProperty("count")); // count false console.log(Foo.prototype.hasOwnProperty("count")); // true console.log(Foo.prototype.hasOwnProperty("get")); // true f.age // -> 25 f.count // -> 100,雖然不是f的ownProperty,但直接讀取該屬性也是能夠的 console.log(Foo.prototype.isPrototypeOf(f)); // -> true console.log(Foo === f.constructor); // -> true
##關於__proto__和prototype的區別
最簡單來講,__proto__屬性是實例對象的原型屬性,prototype是構造函數的原型屬性,二者應該是相等的。如:
function B(){this.name = 'kobe';} B.prototype.age = 20; var b = new B(); alert(b.__proto__ === B.prototype); // true
當使用new關鍵字來調用構造函數時,若是構造函數裏沒有返回任何內容,就會返回this——當前上下文的對象,要否則就返回任意非原始類型的值,如數組,object。如:
var Class1 = function(){return {};}, Class2 = function(){return [];}, Class3 = function(){return function(){};}, Class4 = function(){return 123;}, Person1 = new Class1, // {} Person2 = new Class2, // [] Person3 = new Class3, // function(){} Person4 = new Class4; // function instanceof Class4
##棧stack和堆heap的區別
原始值是存儲在棧中的簡單數據段,也就是說,它們的值直接存儲在變量訪問的位置;引用值是存儲在堆中的對象,也就是說,存儲在變量處的值是一個指針,指向存儲對象的內存處。若是一個值是引用類型的,那麼它的存儲空間將從堆中分配。因爲引用值的大小會改變,因此不能把它放在棧中,不然會下降變量查尋的速度。相反,放在變量的棧空間中的值是該對象存儲在堆中的地址。地址的大小是固定的,因此把它存儲在棧中對變量性能無任何負面影響。
##Number值集合的外邊界:Number.MAX_VALUE和Number.MIN_VALUE
全部ECMAScript數都必須在這兩個值之間,不過計算生成的數值結果能夠不落在這兩個數之間。當計算生成的數大於Number.MAX_VALUE時,它將被賦予值Number.POSITIVE_INFINITY,意味着再也不有數字值,一樣,生成的數值小於Number.MIN_VALUE的計算也會被賦予值Number.NEGATIVE_INFINITY,也再也不有數字值。若是返回的是無窮大值,那麼結果就不能再用在其餘計算。
無窮大的值:Infinity === Number.POSITIVE_INFINITY
,-Infinity === Number.NEGATIVE_INFINITY
,判斷是否有窮的isFinite(123) === true
##數字轉換爲二進制字符串
a=12345, a.toString(2) === "11000000111001"
,與之相對的是 a = parseInt("11000000111001", 2) === 12345
##閉包(closure) ##做用域鏈
做用域鏈:js只有函數做用域和全局做用域。做用域鏈就是從內部函數做用域到外部函數做用域,一直到全局做用域。閉包是簡單來講是函數中使用函數,內部函數使用到外部函數的變量,而外部函數以外的做用域對外部函數的返回值有引用,那麼外部函數就成了一個閉包,內部函數對外部函數的引用鏈就不會銷燬。
閉包意味着內層的函數能夠引用存在於包圍它的函數內的變量,即便外層函數的執行已經終止
閉包主要的應用場景以及一些特色有:
var obj = (function(){ var privateVar; return { get: function(){ return privateVar; }, set: function(value){ privateVar = value } }; })();
(function($, undefined){/*…*/})(jQuery)
但閉包有在for/next循環中使用閉包卻不聲明變量來保存迭代變量當前值的一些風險。閉包容許你引用父函數中的變量,但提供的值並不是該變量建立時的值,而是在父函數範圍內的最終值。
在函數A內定義一個函數B,B對A中的一些變量有引用,那麼A即便運行結束,B對A變量的引用鏈也不會銷燬。因此閉包不能濫用!
##垃圾回收機制 ##循環引用
在函數中聲明一個變量,則將其標記爲「進入環境」,當變量離開環境時,則將其標記爲「離開環境」。
垃圾回收器在運行的時候會給存儲在內存中的全部變量都加上標記(固然,可使用任何標記方式)。而後,它會去掉環境中的變量以及被環境中的變量引用的變量的標記(閉包)。而後銷燬那些帶標記的值並回收它們所佔用的內存空間
引用計數的含義是跟蹤記錄每一個值被引用的次數。當聲明瞭一個變量並將一個引用類型值賦給該變量時,則這個值的引用次數就是1。若是同一個值又被賦給另外一個變量,則該值的引用次數加1。相反,若是包含對這個值引用的變量又取得了另一個值,則這個值的引用次數減1。當這個值的引用次數變成0時,則說明沒有辦法再訪問這個值了,於是就能夠將其佔用的內存空間回收回來。這樣,當垃圾回收器下次再運行時,它就會釋放那些引用次數爲0的值所佔用的內存。
Netscape Navigator3是最先使用引用計數策略的瀏覽器,但很快它就遇到一個嚴重的問題:循環引用。循環引用指的是對象A中包含一個指向對象B的指針,而對象B中也包含一個指向對象A的引用。
function fn() { var a = {}; var b = {}; a.pro = b; b.pro = a; } fn();
以上代碼a和b的引用次數都是2,fn()執行完畢後,兩個對象都已經離開環境,在標記清除方式下是沒有問題的,可是在引用計數策略下,由於a和b的引用次數不爲0,因此不會被垃圾回收器回收內存,若是fn函數被大量調用,就會形成內存泄露。
咱們知道,IE中有一部分對象並非原生js對象。例如,其DOM和BOM中的對象就是使用C++以COM對象的形式實現的,而COM對象的垃圾回收機制採用的就是引用計數策略。所以,即便IE的js引擎採用標記清除策略來實現,但js訪問的COM對象依然是基於引用計數策略的。換句話說,只要在IE中涉及COM對象,就會存在循環引用的問題。
因此,有時需手動切斷JS對象與DOM的鏈接:
$dom._object = null; jsObj._dom = null;