javascript-代码段

目录

apply、call 和 bind 的区别

apply 使用

根据CommonJS规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为global对象的属性。

global.warming = true;

call 使用

上面代码的waiming变量,可以被所有模块读取。当然,这样做是不推荐,输出模块变量的最好方法是使用module.exports对象。

var i = 1;
var max = 30;

module.exports = function () {
  for (i -= 1; i++ < max; ) {
    console.log(i);
  }
  max *= 1.1;
};

bind 使用

上面代码通过module.exports对象,定义了一个函数,该函数就是模块外部与内部通信的桥梁。

加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的module.exports对象。假定有一个一个简单的模块example.js。

// example.js

console.log("evaluating example.js");

var invisible = function () {
  console.log("invisible");
}

exports.message = "hi";

exports.say = function () {
  console.log(message);
}

javascript 操作样式 class

方式一 最基本的方式

function hasClass(ele,cls){
    return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
}

function addClass(ele,cls) {
    if (!hasClass(ele,cls)) {
        ele.className += " "+cls;
    }
}

function removeClass(ele,cls) {
    var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
    ele.className=ele.className.replace(reg,' ');
}

方式二 扩展 classList 实现

function addClass() {

}

常用到的计算

获取 m 到 n 之间的整数随机数

// 包含m, 不包含n
function rnd(m,n) {
  return Math.ceil(Math.random() * (n - m) + m);
}

// 包含n, 不包含m
function rnd(m,n) {
  return Math.floor(Math.random() * (n - m) + m);
}

角度弧度互转

/**
 * 弧度转角度
 */
function a2d(n) {
    return n * 180 / Math.PI;
}

/**
 * 角度转弧度
 */
function d2a(n) {
    return n * Math.PI / 180;
}

IE浏览器版本低于8,提示用户升级

// from http://g.alicdn.com/aliyun/console/1.3.13/scripts/browser-not-supported.js

window._browserIsNotSupported = true;
if(window.attachEvent){
  window.attachEvent('onload', function(){
    var lowestSupportedIEVersion = 8;
    if(window.LOWEST_IE_VERSION != undefined){
      lowestSupportedIEVersion = window.LOWEST_IE_VERSION;
    }
    var el = document.createElement('div'),
        elStyle = el.style,
        docBody = document.getElementsByTagName('body')[0],
        linkStyle = 'color:#06F;text-decoration: underline;';
    el.innerHTML =  '尊敬的用户:<br />'+
        '使用阿里云控制台需要安装Internet Explorer更新版本的浏览器,'+
        '请<a href="http://windows.microsoft.com/zh-cn/internet-explorer/download-ie" style="'+linkStyle+'" target="_blank">下载安装IE' + lowestSupportedIEVersion + '</a>(或更新)。'+
        '也可以在其他浏览器,'+
        '如<a href="http://www.google.com/intl/zh-CN/chrome/" style="'+linkStyle+'" target="_blank">Chrome</a>'+
        '或<a href="http://www.firefox.com.cn/download/" style="'+linkStyle+'" target="_blank">Firefox</a>火狐中打开控制台。';
    // elStyle.width = '100%';
    elStyle.width = '720px';
    elStyle.color = '#000';
    elStyle.fontSize = '14px';
    elStyle.lineHeight = '180%';
    elStyle.margin = '60px auto';
    elStyle.backgroundColor = '#fffbd5';
    elStyle.border = '1px solid #CCC';
    elStyle.padding = '24px 48px';

    docBody.innerHTML = '';
    docBody.appendChild(el);
    // docBody.insertBefore(el,docBody.firstChild);
  });
}

判断对象是否包含某个属性

hasOwnProperty 用来判断某个对象是否含有指定的自身属性。该方法会忽略掉那些从原型链上继承到的属性。

//常规的方式,包括我之前在循环中判断都是以该值是否为空来判断的,其实:
// 

obj.hasOwnProperty(prop); 

in, 判断对象中的属性,一个字符串类型的属性名或者数字类型的数组索引。包含自身属性及从父及(原型链中继承过来的属性)

// 判断原型中有该属性,但是自己属性中没有的属性
function hasPropertyInPrototype(obj, prop) {
    return !obj.hasOwnProperty(prop) && prop in obj;
}

与 Array 相关的的

Array 的 remove 实现

/**
 * 删除数组中的元素,(下面的写法为以后js提供remove做兼容)
 */
Array.prototype.remove = Array.prototype.remove || function(obj) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] == obj) {
            this.splice(i, 1);
            i--;
        }
    }
}

判断是否为数组类型 : isArray

1、首先我会想到 typeof 来判断

// typeof操作符。对于Function、String、Number、Undefined这几种类型的对象来说,不会有什么问题,但是针对Array的对象就没什么用途了: 

typeof [] ;
typeof null  // 两个都返回object,其实是无法判断到底是不是数组的,

2、于是,又想到了 instanceof ,instanceof 用来检测对象的原型链是否指向构造函数的prototype对象

var arr = []; 
alert(arr instanceof Array); // true 

3、对象的constructor属性。除了instanceof,我们还可以利用每个对象都具有constructor的属性来判断其类型,于是乎我们可以这样做:

var arr = [];   
alert(arr.constructor == Array); // true

4、2/3在一般的情况下已经可以满足我们的需求,但是在某个包含多个框架(frame/iframe)页面的情况下却又不成立, 因为实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的Array构造函数

var iframe = document.createElement('iframe'); 
document.body.appendChild(iframe); 
xArray = window.frames[window.frames.length-1].Array; 
var arr = new xArray(1,2,3); // [1,2,3] 
// 哎呀! 
arr instanceof Array; // false 
// 哎呀呀! 
arr.constructor === Array; // false

//由于每个iframe都有一套自己的执行环境,跨frame实例化的对象彼此是不共享原型链的,因此导致上述检测代码失效

5、最终解决方法

function isArray(obj) {
  return Object.prototype.toString.call(obj) === '[object Array]'; 
}

使用sort对数组进行排序

// 1、对数字进行排序

var arr = [30, 0.3, 22,190, 311, 222];
arr.sort();
[0.3, 190, 22, 222, 30, 311]    // 很显然结果不是我们想要的

// ---
var arr = [30, 0.3, 22,190, 311, 222];
arr.sort(function(a,b) {
    return a - b;
});
[0.3, 22, 30, 190, 222, 311]    // 结果正确 

// 2、对字母进行排序

var arr = ['Alert', 'CQ','banana'];

console.info ( arr.sort() );
// ["Alert", "CQ", "banana"]    // 结果与我们预期的不同


// --
var arr = ['alert', 'cQ','banana'];

console.info ( arr.sort() );
// ["alert", "banana", "cQ"] // 似乎是我们想要的结果,往下看

// --
var arr = ['alert', 'cQ2','banana', 'cq1'];

console.info ( arr.sort() );
// ["alert", "banana", "cQ2", "cq1"] // 按理说cQ2应该排在cq1的后面,于是想到数字的比较方式

// ---
var arr = ['alert', 'cQ2','banana', 'cq1'];

console.info ( arr.sort(function(a,b) {
    return a - b;
}) );
["alert", "cQ2", "banana", "cq1"] // 这样也不行

// ---
var arr = ['alert', 'cQ2','banana', 'cq1'];

console.info ( arr.sort(function(a,b) {
    if( a > b) {
        return 1;
    } else if(a < b) {
        return -1;
    } else {
        return 0;
    }
}) );
// ["alert", "banana", "cQ2", "cq1"]    //还是不行

// ---
var arr = ['alert', 'cQ2','banana', 'cq1'];

console.info ( arr.sort(function(a,b) {
    a = a.toLowerCase(), b = b.toLowerCase();

    if( a > b) {
        return 1;
    } else if(a < b) {
        return -1;
    } else {
        return 0;
    }
}) );
//["alert", "banana", "cq1", "cQ2"] // 这才是我们想要的结果,(但对于B2,ba这两个该2在前还是在后需要根据需求在做处理了,这里默认是按照字符编码顺序来的。2->50,a -> 97)

说一下我们在这里犯过的几个错误

  • 操作符 - 的错误使用: 直接拿数字的比较方式对字母进行比较, 比如 a - b 的使用。操作数是字符串/boolean/null/undefined时,后台会调用Number()函数将其转化为数字,然后再根据相应的规则执行减法计算,如果转换结果是NaN,则减法结果就是NaN; if(NaN) {} 这样的条件永远不成立,则排序就无从谈起了。所以我们该用 >< 判断。

  • 操作符 <>的错误使用: 对于数字是不会出现问题的,错误主要出现在对字符串(这里值得是字母组成的字符串,不对汉字进行讨论)的操作, 看一下个例子: js var result = "Brick" < "alphabet"; // true; var result = "Brick".toLowerCase() < "alphabet".toLowerCase(); // false 原因:在比较字符串时,实际比较的是两个字符串中对应位置的每个字符的字符编码。已知大写字母的字符编码(A-Z -> 65-90)全部小于小写的字符编码(a-z -> 97-122) 。数字对应(0-9 -> 48-> 57)。

页面加载完成,执行多个函数

function addLoadEvent(func) {
    var oldonload = window.onload;
    if (typeof window.onload != 'function') {
        window.onload = func;
    } else {
        window.onload = function() {
            oldonload();
            func();
        }
    }
}

insertAfter

function insertAfter(newElement, targetElement) {
    var parent = targetElement.parentNode;
    if (parent.lastChild == targetElement) {
        parent.appendChild(newElement);
    } else {
        parent.insertBefore(newElement, targetElement.nextSibling);
    }
}

resize image

// 忘了从哪里复制的了
var resizePicWidth = function(selector, pic_width) {
    $(selector + " img").each(function() {
        var img = $(this);
        var realWidth; //真实的宽度
        var realHeight; //真实的高度
        //这里做下说明,$("<img/>")这里是创建一个临时的img标签,类似js创建一个new Image()对象!
        $("<img/>").attr("src", $(img).attr("src")).load(function() {
            /*
              如果要获取图片的真实的宽度和高度有三点必须注意
              1、需要创建一个image对象:如这里的$("<img/>")
              2、指定图片的src路径
              3、一定要在图片加载完成后执行如.load()函数里执行
             */
            realWidth = this.width;
            realHeight = this.height;
            //如果真实的宽度大于规定的宽度就按照100%显示
            if (realWidth >= pic_width) {
                $(img).css("width", (pic_width) + "px");
            } else { //如果小于浏览器的宽度按照原尺寸显示
                $(img).css("width", realWidth + 'px');
            }
        });
    });
};

获取jquery 获取浏览器宽高、滚动条高度、屏幕的宽高

;(function($) {
    $.extend($.browser, {
        client: function() {
            return {
                width: document.documentElement.clientWidth,
                height: document.documentElement.clientHeight,
                bodyWidth: document.body.clientWidth,
                bodyHeight: document.body.clientHeight
            };
        },
        scroll: function() {
            return {
                width: document.documentElement.scrollWidth,
                height: document.documentElement.scrollHeight,
                bodyWidth: document.body.scrollWidth,
                bodyHeight: document.body.scrollHeight,
                left: document.documentElement.scrollLeft + document.body.scrollLeft,
                top: document.documentElement.scrollTop + document.body.scrollTop
            };
        },
        screen: function() {
            return {
                width: window.screen.width,
                height: window.screen.height
            };
        },
        isIE6: $.browser.msie && $.browser.version == 6,
        isMinW: function(val) {
            return Math.min($.browser.client().bodyWidth, $.browser.client().width) <= val;
        },
        isMinH: function(val) {
            return $.browser.client().height <= val;
        }
    })
})(jQuery);

点点滴滴

* Get element by id
 */ 
function get(element){
    if (typeof element == "string")
        element = d.getElementById(element);
    return element;
}

/**
 * Attaches event to a dom element
 */
function addEvent(el, type, fn){
    if (w.addEventListener){
        el.addEventListener(type, fn, false);
    } else if (w.attachEvent){
        var f = function(){
          fn.call(el, w.event);
        };          
        el.attachEvent('on' + type, f)
    }
}


/**
 * Creates and returns element from html chunk
 */
var toElement = function(){
    var div = d.createElement('div');
    return function(html){
        div.innerHTML = html;
        var el = div.childNodes[0];
        div.removeChild(el);
        return el;
    }
}();

function hasClass(ele,cls){
    return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
}

function addClass(ele,cls) {
    if (!hasClass(ele,cls)) ele.className += " "+cls;
}

function removeClass(ele,cls) {
    var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
    ele.className=ele.className.replace(reg,' ');
}

/**
 * 根据样式名称(单个)获取元素
 * @param {Object} obj 在那个元素下查找 document/[元素对象]
 * @param {Object} cls 样式名称
 */
function getClassEles(obj, cls) {
    if (obj.getElementsByClassName) {
        return obj.getElementsByClassName(cls);
    } else {
        var tags = obj.getElementsByTagName('*');
        var aTargetEles = [];

        var oReg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
        for (var i = 0; i < tags.length; i++) {
            if (tags[i].className.match(oReg)) {
                aTargetEles.push(tags[i]);
            }
        }
        return aTargetEles;
    }
}

参考链接

留言

comments powered by Disqus