惰性載入函數
爲了避免每次都判斷瀏覽器能力,影響效率,將判斷放在返回的函數外面。(惰性載入)
惰性載入函數表示函數執行的分支僅會發生一次。
有兩種實現惰性載入的方式:
- 第一種是在函數第一次被調用時在處理函數。在第一次調用的過程中,該函數會被覆蓋爲另外一個按合適的方式執行的函數,這樣任何對原函數的調用都不會再經過執行的分支了。
- 第二種是在聲明函數時就指定適當的函數。第一次調用函數時就不會損失性能了,而在代碼首次加載時會損失一點性能。
其實,惰性載入是js設計模式之一,即惰性模式。啊,原來,還有這麼個高大上的名字。js設計模式中有很多平時很常見,但是不知道名字的模式。在下面的學習中,我將不斷總結。
注:下文中,我使用事件註冊、樣式獲取做了兩個例子。你可以學習到如何寫惰性載入函數,其他兼容的方法也就不在話下了。
事件註冊兼容
/* 爲了避免每次都判斷瀏覽器能力,影響效率,將判斷放在返回的函數外面(惰性載入)*/
/*addEventListener -- IE9以上
attachEvent -- IE9(不包括IE9)支持,冒泡階段纔會被調用
1. 三種註冊事件,回調函數中this指向不一樣
使用addEventListener註冊的事件,回調函數中this指向target
使用attachEvent註冊的事件,回調函數中this指向window
2. 三種註冊事件中,回調函數接收事件對象方式不一樣
在ie下,事件對象是在全局的,也就 window下,做爲window的一個屬性
在其他瀏覽器,都做爲方法的第一個參數傳入,所以這樣寫是爲了兼容
例:window.onload =function () {
var div = document.getElementById("dvd1");
function huidiao(e){
console.log(e+"就是當前的事件對象")
console.log( this+ "就是當前你點擊的對象");
alert("我是div的點擊事件,所有瀏覽器中,我的功能都是彈出來這句話!");
}
//通用的
div.onclick = huidiao;
//ie9以上才支持
div.addEventListener("click",huidiao)
//ie9(不包括9)以下支持的
div.attachEvent("onclick",function(){
huidiao.call(div, window.event);
})
}
所以要統一設置回調函數中this指向target,事件對象方式一致
*/
事件兼容+惰性載入思想實現:
//方法二:聲明函數時就指定適當的函數
var registerEvent = (function(){
if (window.addEventListener) {
return function(target, type, handler) {
console.log(this); //this指向window
target.addEventListener(type, handler, false);
}
} else if (window.attachEvent) {
return function(target, type, handler) {
target.attachEvent("on" + type, function() {
handler.call(target, window.event);
});
}
} else {
return function(target, type, handler) {
target["on" + type] = handler;
}
}
})();
//方法一:第一次調用函數時,該函數覆蓋爲另一個更爲合適執行的函數
function registerEvent(target, type, handler) {
if (window.addEventListener) {
console.log("------");
registerEvent = function(target, type, handler) {
console.log(this); //this指向window
console.log(target);
target.addEventListener(type, handler, false);
}
} else if (window.attachEvent) {
registerEvent = function(target, type, handler) {
target.attachEvent("on" + type, function() {
handler.call(target, window.event);
});
}
} else {
registerEvent = function(target, type, handler) {
target["on" + type] = handler;
}
}
return registerEvent(target, type, handler);
}
//測試代碼
var div1 = document.getElementById("div1");
console.log(div1);
registerEvent(div1, "click", function(e) {
console.log(e + "就是當前的事件對象");
console.log(e.type);
console.log(this + "就是當前你點擊的對象");
console.log(this.innerHTML);
alert("我是div的點擊事件,所有瀏覽器中,我的功能都是彈出來這句話!");
});
registerEvent(div1, "click", function(e) {
alert("2");
});
獲取元素樣式+惰性載入兼容寫法
function getStyle(elem,property){
return window.getComputedStyle?window.getComputedStyle(elem,null).getPropertyValue(property):elem.currentStyle.getAttribute(property);
}
改革版:
//方法一:第一次調用函數時,該函數覆蓋爲另一個更爲合適執行的函數
function getStyle(obj,propertyName){
if(window.getComputedStyle){
getStyle = function(obj,propertyName){
return window.getComputedStyle(obj,null).getPropertyValue(propertyName);
}
}else{
getStyle = function(obj,propertyName){
return obj.currentStyle.getAttribute(propertyName);
}
}
return getStyle(obj,propertyName);
}
//方法二:聲明函數時就指定適當的函數(立即執行函數)
var getStyle = (function(){
if(window.getComputedStyle){
return function(obj,propertyName){
return window.getComputedStyle(obj,null).getPropertyValue(propertyName);
}
}else{
return function(obj,propertyName){
return obj.currentStyle.getAttribute(propertyName);
}
}
})();
//測試代碼:
//html: <div id="div1" style="width:100px; background-color:red" >123</div>
var div1 = document.getElementById("div1");
console.log(getStyle(div1,'width'));
console.log(getStyle(div1,'background-color'));
transform兼容寫法
問題引入:
要想讓元素動起來,修改元素的left,top值,但會引起頁面重繪,而transform不會,所以要優先使用transform。
function getTransform() {
var transform = '',
divStyle = document.createElement('div').style,
transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'oTransform'];
//通過循環找出瀏覽器識別的那個,in操作符用於判斷是否識別
for (var i = 0,len = transformArr.length; i < len; i++) {
if (transformArr[i] in divStyle) {
return transform = transformArr[i];
}
}
return transform;
}
console.log(getTransform());
該方法用於獲取瀏覽器支持的transform屬性。如果返回的是空字符串,則表示當前瀏覽器並不支持transform,此時需要使用left,top值改變元素位置。如果支持,就改變transform值。
判斷是否選擇了內容
var txt;
if(window.getSelection){
txt = window.getSelection().toString();
}else{
txt = document.selection.createRange().text;
}