惰性载入函数
为了避免每次都判断浏览器能力,影响效率,将判断放在返回的函数外面。(惰性载入)
惰性载入函数表示函数执行的分支仅会发生一次。
有两种实现惰性载入的方式:
- 第一种是在函数第一次被调用时在处理函数。在第一次调用的过程中,该函数会被覆盖为另外一个按合适的方式执行的函数,这样任何对原函数的调用都不会再经过执行的分支了。
- 第二种是在声明函数时就指定适当的函数。第一次调用函数时就不会损失性能了,而在代码首次加载时会损失一点性能。
其实,惰性载入是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;
}