Git Product home page Git Product logo

jsskills's People

Contributors

lynxerzhang avatar

Watchers

 avatar

jsskills's Issues

“use strict” 标识符作用记录

gskinner的Createjs工具库是使用es5语法编写的,其中有一个deprecate方法。

this.createjs = this.createjs||{};
createjs.deprecate = function(fallbackMethod, name) {
	"use strict"; //此处的use strict可以将如下的匿名函数中的this限制为undefined, 如果不添加,就是全局的window。
	return function() {
		var msg = "Deprecated property or method '"+name+"'. See docs for info.";
		console && (console.warn ? console.warn(msg) : console.log(msg));
		return fallbackMethod && fallbackMethod.apply(this, arguments);
	}
};

在es5中,"use strict"的具体有哪些作用

css使用一个class去覆盖其它class中的属性的优先级问题

使用一个class去覆盖另一个class中声明的属性

但是这里面又会引出一个问题,如何判断一个class是否能够覆盖另一个class中的属性,这篇教程详细叙述了如何计算css specificity value

需要注意,css specificity value的数值不是十进制的,所以它使用的是诸如,(1, 0, 0, 0),(0, 1, 0, 0),也就是其中有逗号分隔。

以(1, 0, 0, 0)为例,从左到右specificity value从高到低,依次递减。第一等是内联元素的style,第二等为元素id,第三等为元素的class,伪类,属性选择,第四类为元素本身。同时要注意!important的影响,其中pseudo-class和pseudo-elements是不同的,比如first-line就是pseudo-elements,计算下来为(0, 0, 0, 1),而不像pseudo-class为(0, 0, 1, 0)

设置css颜色值

var colorToRGB = (function(){
    return function(colorHex) {
        if(typeof colorHex == 'number'){
            colorHex = "#" + colorHex.toString(16);
        }
        var hashTag = colorHex.charAt(0) === "#";
        if(hashTag){
            colorHex = colorHex.slice(1);
        }
        var shorthand = colorHex.length == 3;
        var alpha = colorHex.length == 8;
        if(shorthand){
            var h = colorHex.split("").map(function(s){
                return s + s;
            });
            colorHex = h.join("");
        }
        var hex = parseInt(colorHex, 16); 
        return "rgb" + (alpha ? "a" : "") + "(" + 
                        (alpha ? (((hex >> 24) & 0xFF) + ", ") : "") + 
                        ((hex >> 16) & 0xFF) + ", " + ((hex >> 8) & 0xFF) + ", " + 
                        (hex & 0xFF) + ")";
    }
})();
console.log(colorToRGB('#ffff6600')); // rgba(255, 255, 102, 0)
//如下输出都为rgb(255, 102, 0)
console.log(colorToRGB('ff6600'));
console.log(colorToRGB('#f60'));
console.log(colorToRGB('f60'));
console.log(colorToRGB(0xff6600));

CSS线性动画研究

var root = document.getElementById("playground");

var e = createChild();
root.appendChild(e);

function createChild() {
	var e = document.createElement("div");
	e.style.position = "absolute";
	e.style.width = "50px";
	e.style.height = "10px";
	e.style.top = "10px";
	e.style.left = "500px";
	e.style.background = "blue";
	return e;
}

setTimeout(function(){
	var d = new DomAnimationX(e, {"x":-550 * .5, "duration":5000 * .5});
	d.add("complete", function(){
		setTimeout(function(){
			d = new DomAnimationX(e, {"x":-550, "duration":5000 * .5});
			f.add(d);
		}, 3000);
	})
	var f = new TickDomManager();
	f.add(d);
	f.start();
}, 0);

//使用transform对dom进行位移,同时又使用transition监听dom上的transfrom位移来达到线性动画的目的。
var TickDomManager = (function(){
	function TickDomManager(){
		this.domAnList = [];
		var self = this;
		this.tick = new Animation(function(t){
			self.tickCallback(t);
		});
	}
	var p = TickDomManager.prototype;
	p.start = function() {
		this.tick.start();
		var len = this.domAnList.length;
		var d;
		for(var i = 0; i < len; i ++){
			d = this.domAnList[i];
			if(d){
				d.start();
			}
		}
	}
	p.stop = function() {
		this.tick.stop();
		var len = this.domAnList.length;
		var d;
		for(var i = 0; i < len; i ++){
			d = this.domAnList[i];
			if(d){
				d.stop();
			}
		}
	}
	p.tickCallback = function(time) {
		var len = this.domAnList.length;
		var d;
		for(var i = 0; i < len; i ++){
			d = this.domAnList[i];
			if(d){
				d.tick(time);
			}
		}
	}
	p.add = function(domAn) {
		domAn.start();
		var self = this;
		domAn.add("complete", function(){
			self.remove(this);
			this.destroy();
		}.bind(domAn));  //bind 方法执行上下文环境
		this.domAnList.push(domAn);
	}
	p.remove = function(domAn) {
		var len = this.domAnList.length;
		var d;
		for(var i = len - 1; i >= 0; i --){
			d = this.domAnList[i];
			if(d && d == domAn){
				break;
			}
		}
		if(i >= 0 && i < len){
			this.domAnList.splice(i, 1);
		}
	}
	return TickDomManager;
})();

var DomAnimationX = (function(){
	function DomAnimationX(dom, data) {
		this.dom = dom;
		this.data = data;
		this.duration = data.duration;
		this.lifeDuration = this.duration;
		this.delay = data.delay || 0;
		this.watch = createEventDispatch();
	}
	var p = DomAnimationX.prototype;
	p.destroy = function() {
		this.dom = null;
		this.data = null;
		this.watch = null;
	}
	p.start = function() {
		Animation.setTransition(this.dom, "transform " + 
		                this.lifeDuration + "ms linear " + this.delay + "ms");
		Animation.setTransform(this.dom, "translateX(" + this.data.x + "px)");
		this.dispatch("start");
	}
	p.stop = function() {
		var d = this.data.x * ((this.duration - this.lifeDuration) / this.duration);
		Animation.setTransition(this.dom, "");
		Animation.setTransform(this.dom, "translateX(" + d + "px)");
		this.dispatch("stop");
	}
	p.tick = function(time) {
		if(this.lifeDuration <= 0){
			this.lifeDuration = 0;
			this.dispatch("complete");
			return;
		}
		this.lifeDuration -= time;
	}
	p.add = function(e, h) {
		this.watch.add(e, h);
	}
	p.remove = function(e, h) {
		this.watch.remove(e, h);
	}	
	p.dispatch = function(e) {
		this.watch.dispatch(e);
	}
	return DomAnimationX;
})();

var createEventDispatch = (function(){
	return function() {
		var watch = {};
		watch.listener = {};
		watch.add = function(e, h){
			var s = this.listener[e];
			if(!s){
				this.listener[e] = [h];
			}
			else{
				if(s.indexOf(h) < 0){
					s.push(h);
				}
			}
		}
		watch.remove = function(e, h) {
			var s = this.listener[e];
			if(s){
				var len = s.length;
				if(arguments.length == 1){
					s.length = 0;
					s = null;
					this.listener[e] = s;
				}else{
					for(var i = len - 1; i >= 0; i--){
						if(s[i] == h){
							break;
						}
					}
					if(i >= 0 && i < len){
						s.splice(i, 1);
					}
				}
			}
		}
		watch.dispatch = function(e){
			var s = this.listener[e];
			if(s){
				var len = s.length;
				var d;
				for(var i = len - 1; i >= 0; i --){
					d = s[i];
					d(e);
				}
			}
		}
		return watch;
	}
})();

var Animation = (function(){
	function Animation(callback){
		this.callback = callback;
		this.running = false;
                this.shouldKill = false;
                this.last = 0;
                this.now = 0;
	}
	Animation.setTransition = function(dom, trans) {
		dom.style.transition = trans;
		dom.style.webkitTransition = trans;
		dom.style.mozTransition = trans;
		dom.style.msTransition = trans;
		dom.style.oTransition= trans;
	}
	Animation.setTransform = function(dom, trans){
	        dom.style.transform = trans;
	        dom.style.webkitTransform = trans;
	        dom.style.mozTransform = trans;
	        dom.style.msTransform = trans;
	        dom.style.oTransform = trans;
	}
        Animation.request =    (function(){
		return window.requestAnimationFrame   || 
	        window.webkitRequestAnimationFrame ||
	        window.mozRequestAnimationFrame    || 
	        window.oRequestAnimationFrame      || 
	        window.msRequestAnimationFrame     || 
	        function(callback){
	            callback();
	        };
	})();
	var p = Animation.prototype;
	p.start = function() {
		this.last = new Date().getTime();
		this.shouldKill = false;
		if (!this.running) {
		    this.running = true;
		    this.render();
		}
	};
	p.stop = function() {
		this.shouldKill = true;
		this.last = 0;
		this.now = 0;
	};
	p.toggle = function() {
		if (this.running) {
			this.stop();
		}
		else {
			this.start();
		}
	};
	p.render = function() {
		if(this.shouldKill) {
			this.shouldKill = false;
		    this.running = false;
		}
		if (this.running) {
			this.now = new Date().getTime();
		    if (this.callback) {
		        this.callback(this.now - this.last);
		    }
		    this.last = this.now;
		    var self = this;
		    //Animation.request的调用需要如此,不然会报错,原因是该方法上下文执行环境被修改
		    Animation.request.call(null, function(){
		    	self.render();
		    });
		}
	};
	p.dispose = function() {
	    this.stop();
	    this.callback = null;
	    this.running = false;
	    this.shouldKill = false;
	};
	return Animation;
})();

script标签中的defer和async的意义

如果什么标签都不加的话,代码加载和执行是同步的,它会中断解析document,直到它完成执行,并且代码的加载和执行的顺序都是根据script标签的位置决定的。

defer标签会在document还在加载解析的过程中去下载对应的script, 但是并不执行,必须等到document解析全部完成才会去执行对应的script, 并且执行的顺序是根据script标签的位置来决定的。可以理解成执行script的代码是放在DOMContentLoaded事件回调中。

async标签会在document还在加载解析的时候去下载对应的script, 但是下载好后会中断document的解析, 去执行之前下载好的script, 同时async标签不会保证按照script的顺序来执行。

//@see https://30secondsofinterviews.org/
What are defer and async attributes on a <script> tag?

Note: both attributes must only be used if the script has a src attribute (i.e. not an inline script).
<script src="myscript.js"></script>
<script src="myscript.js" defer></script>
<script src="myscript.js" async></script>

git 删除文件使用记录

参考介绍git clean 命令
中文参考介绍git clean 命令

基本上常用的就是 git clean -fn,这里f是强制删除(force)之意, n是提示,也就是这个删除不是真删除,它会列出将会删除的文件,需要你来确认,没有问题了,可以放心使用git clean -f
image

也可以使用git clean -f -i, 会调出交互式询问窗口,这样更安全,不但列出即将删除的文件,还会询问你是如何计划的,删除或者什么都不做退出。

image

利用 git whatchanged --stat 命令查看修改历史,比单纯git log更为详细直观

Xshell git log 乱码问题

Xshell 属性中设置UTF-8

参考

git config --global i18n.commitencoding utf-8
git config --global i18n.logoutputencoding utf-8
export LESSCHARSET=utf-8

html中a标签元素绑定点击事件的方法讨论

可以参考该讨论

<a id="myLink" href="javascript:MyFunction();">link text</a> //bad
<a id="myLink" href="#" onclick="MyFunction();">link text</a> //good
<a id="myLink" href="#" onclick="MyFunction();return false;">link text</a> //better

....

获取浏览器中Cookie值的问题

//获取指定cookie值
function readCookie(name) {
    var g = new RegExp('(?:^|;)\\s*' + name + '\\s*=\\s*([^;]+)');
    var s = document.cookie;
    var d = null;
    if (g.test(s)) {
        d = s.match(g);
        if(d){
            d = d.pop();
        }
    }
    return d;
}

如上实现中的正则表达式做过一个优化,就是使用'非捕捉group'来简化返回值,也就是?:修饰符,
其中字符串的match函数的返回内容,会根据填入的正则表达式是否添加全局搜索修饰符g而不一样,
如果没有填入g,它的返回形式和RegExp的exec方法很像,会返回各种capture group和index值,如果
添加g,返回的就是简单的数组匹配项。

详细讨论了如何用最少的代码来获取指定cookie

关于cookie的介绍

关于读取cookie,需要unescape,写入cookie,需要escape

array的handle array方法使用记录

@see https://github.com/Chalarangelo/30-seconds-of-code
//indexOfAll
var indexOfAll = (function(){
    return function(ary, val) {
        return ary.reduce(function(prev, cur, i){
            return cur === val ? prev.concat(i) : prev;
        }, []);
    }
})();
indexOfAll([1, 2, 3, 1, 2, 3], 1); 
// [0,3]

//getLongItem
var getLongItem = (function(){
    return function (val){
        var c = arguments.length - 1;
        var list = [val];
        if(c > 0){
            for(var i = 0; i < c; i ++){
                list.push(arguments[i + 1]);
            }
        }
        return list.reduce(function(prev, current){
            return current.length > prev.length ? current : prev;
        });
    }
})();
getLongItem([1, 2, 3], [1, 2], [1, 2, 3, 4, 5]); 
// [1, 2, 3, 4, 5]

//mapObject
var mapObject = (function(){
    return function(ary, keyFunc, valueFunc) {
        var d = [ary.map(keyFunc), ary.map(valueFunc)];
        return d[0].reduce(function(prev, current, index){
            return prev[current] = d[1][index], prev;
        }, {});
    }
})();
var result = mapObject(["a1+1", "a2+2", "a3+3"], function(a){
	return a.split("+")[0];
}, function(a){
	return a.split("+")[1]
});
//{a1: "1", a2: "2", a3: "3"}

//partitionReduce 
var partitionReduce = (function(){
    return function(ary, check) {
        return ary.reduce(function(prev, cur, index, array){
            prev[check(cur) ? 0 : 1].push(cur);
            return prev;
        }, [[], []]);
    }
})();
var ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
partitionReduce(ary, function(n){
	return n % 2 == 0;
});
//[[2, 4, 6, 8, 10],[1, 3, 5, 7, 9]]


//pickFilter 
var pickFilter = (function(){
    return function(obj, ary){
        return ary.reduce(function(prev, cur, index, array){
            if(obj.hasOwnProperty(cur)){
                prev[cur] = obj[cur];
            }
            return prev;
        }, {});
    }
})();
pickFilter({ a: 1, b: '2', c: 3 }, ['a', 'b']); // {a: 1, b: "2"}

css last-child 不起作用研究

可参考该描述,以及这篇,从父级定位至子级,希望子级中的最后一个元素执行额外的样式,发现不起作用,可以查看该父级是否只有一种该类型的子级,比如父级的类型为ul,子级如果都是li,则可以生效,如果其中夹杂着其它类型元素,比如span之类,则不起作用

如下代码,html 和 css 可以在codepen中调试

<ul>
    <li>3</li>
    <li class="complete">1</li>
    <li class="complete">2</li>
    <li>3</li>
    <li>4</li>
    <span></span>
</ul>
//如果span不加在最后,而是成为ul的第一个元素,也可以正常执行
li.complete:last-child{
    background-color: green;
}
li.complete:first-of-type {
  background-color: green;
}

同时这里也有详细介绍

js中使用var或者let来声明变量有什么不同?

这个帖子很好的说明了两者的区别,现在整理如下:

1. 在function外声明的变量, let无法通过window来访问到

var canfound = 2;
let cannotFound = 2;
console.log(window.canfound); //2
console.log(window.cannotFound); //undefined

2. let 无法被重新声明

let canNotBeRedeclaration = 1;
let canNotBeRedeclaration = 2; 
//Identifier 'canNotBeRedeclaration' has already been declared

var canBeRedeclaration = 1;
var canBeRedeclaration = 2;  
console.log(canBeRedeclaration); //2

3. let在function中的作用域

//let
function testletScope() {
  //无法访问i  ReferenceError: i is not defined
  for(let i = 0; i < 5; i ++){
     //可以访问i
  }
  //无法访问i ReferenceError: i is not defined
}

//var
function testvarScope() {
  //由于变量提升,i为undefined 
  for(var i = 0; i < 5; i ++){
     //可以访问i
  }
  //可以访问i
}

使用js设置渐变色遇到的问题

利用css的backgroundImage属性可以设置渐变色,但是利用js来动态设置时,设置颜色值的时候有个地方需要注意,不然可能造成显示问题(比如css属性添加不上)。

这个需要注意的就是颜色值本身。

问题重现:

//我需要把这个数组中的每一个项,变成字符串,比如第一项0xff2a46,经过转换就是#ff2a46,

var d = [0xff2a46,0xff7522,0xd8c206,0x09d49d,0x3c78ff,0x991aff];

//利用toString方法,可以很容易做到。
//下面这个数组就是转换过的。

var e = ["#ff2a46", "#ff7522“, "#d8c206", "#9d49d", "#3c78ff", "#991aff"];

但是很快发现,无法添加渐变色,查了好久发现0x09d49d变成了"#9d49d", 这个本身没有问题,但是就是因为少了个0,就不显示渐变色了,
所以,做了个判断,24位颜色值的16进制值字符串因为长度最长就是6,所以可以判断下,如果长度不满6,字符串前面就填充0。
那“#9d49d”就变成了“#09d49d”,修改后发现显示正常

//gradientBackgroundColorList传进来的是一个颜色值数组,比如[0xFF0000, 0xFFFF00, 0xFF00FF]
Object.defineProperty(CoreComment.prototype, "gradientBackgroundColorList", {
        get: function () {
            return this._gradientBackgroundColorList;
        },
        set: function (c) {
            this._gradientBackgroundColorList = c;
            if(this._gradientBackgroundColorList){
                var list = this._gradientBackgroundColorList;
                var g_css = ["left"];
                for(var i = 0; i < list.length; i ++){
                    g_css.push("#" + list[i].toString(16)); //这个版本粗看没有什么问题
                }
                this.dom.style.backgroundImage = "-webkit-linear-gradient(" + g_css.join(",") + ")";
            }
            else{
                this.dom.style.backgroundImage = "none";
            }
        },
        enumerable: true,
        configurable: true
});
//修正版本
Object.defineProperty(CoreComment.prototype, "gradientBackgroundColorList", {
        get: function () {
            return this._gradientBackgroundColorList;
        },
        set: function (c) {
            this._gradientBackgroundColorList = c;
            if(this._gradientBackgroundColorList){
                var list = this._gradientBackgroundColorList;
                var g_css = ["left"];
                var c = "";
                for(var i = 0; i < list.length; i ++){
                    c = list[i].toString(16);
                    if(c.length < 6){
                        c = (new Array((6 - c.length) + 1).join("0")) + c; //关键在于这个判断,如果字符长度不满6,就需要用0来填充
                    }
                    g_css.push("#" + c);
                }
                this.dom.style.backgroundImage = "-webkit-linear-gradient(" + g_css.join(",") + ")";
            }
            else{
                this.dom.style.backgroundImage = "none";
            }
        },
        enumerable: true,
        configurable: true
});

在js中如何进行标签页是否切换的判断?

visibilitychange 这个事件只能针对当前标签页是否失去焦点来进行判断,所以需要再加上判断document的hidden属性来做到对标签页是否切换的判断。

var tabPageVisibilityManager = (function(){
    var hiddenProperty = ["hidden", "webkitHidden", "mozHidden", "msHidden"];
    var len = hiddenProperty.length;
    var propertyKey = "";
    for(var i = 0; i < len; i ++){
        if(hiddenProperty[i] in document){
            propertyKey = hiddenProperty[i];
            break;
        }
    }
    var eventKey = "";
    if(propertyKey && propertyKey != ""){
        eventKey = propertyKey.replace(/hidden/i, "visibilitychange");
    }
    return function(pause_callback, resume_callback) {
        document.addEventListener(eventKey, function(){
            if(!document[propertyKey]){
                if(resume_callback != null){
                    resume_callback();
                }
            }else{
                if(pause_callback != null){
                    pause_callback();
                }
            }
        });
    }
})();

tabPageVisibilityManager(function(){
    console.log("pause");
}, function(){
    console.log("resume");
});

git rebase基础使用记录

彻底搞懂git rebase
Git Book关于git rebase描述
Git Book关于git rebase交互式描述
常用git命令详解

详细阐述了git rebase命令

可以发现这个命令如果在没有push到远程的分支上运用,或者说只是在本地分支单人操作,不存在多人协作还是安全的。
最常用的组合是修改历史命令 git rebase -i HEAD~2 (这个HEAD不一定是指master, ~2就是往前倒退2个commit)

常见场景可以说是譬如收到一个bug需要修改,这时候切出了一个分支专门修改bug,这个分支是自己单独进行修改的,但是因为有其它事情,在还没有完成的情况下就commit了,或者是习惯性commit,这时会有很多无意义的commit,这当然是允许的,但是对以后排查这个bug的修改会非常不利,很多commit实际上只是为了修复一个bug。

这时候git rebase -i 命令可以排上用场了。它可以把之前十几个commit压缩成一个commit!

示例为master和bb分支

如下所示,最新提交的commit是在最下面的,也就是 516a658, 这2个提交我想合并成一个commit, 根据如下注释提示,进行修改,默认都是pick,也就是不做任何修改历史commit的操作。
image
方便期间,可以输入缩写,譬如如下,r和s分别代表reword, squash。
image
然后wq保存退出。发现出现如下界面。这是修改commit 提交信息的界面,根据提示可以发现我们可以修改这个commit信息。
image
可以不修改,直接wq保存退出,这时进入合并阶段,这时候所有的commit提交信息都会显示在这里,可以删除一些commit不需要的信息,这样最终合并就不会包含那些commit。
image
继续wq保存退出,发现成功合并这些commits为一个commit!

合并结束后,这时候可以和master做合并了,可以git rebase master 也可以git merge master。
如果master在我们修改的时候已经有新的提交了,那需要注意git rebase可能会有冲突,这个和git merge一样,但是git rebase的好处就是可以把提交历史保持线性,尽管实际开发历史不一定是如此标准的线性。

如果master正好处在当前分支上游,那么即使使用git rebase, 也正好是fast-forward。
image

如果包含有冲突,这很正常,因为分叉提交了,而且即便是使用git merge也会有冲突,
image

按照上面的提示进行修改冲突, git add 后 继续git rebase --continue,如果在rebase的任何阶段后悔了,可以使用git rebase --abort消除任何git rebase的影响和修改,回到最初始阶段。
image

修改完冲突后, 继续git rebase --continue

image

没有问题!这时候查看git log发现,分支和master的提交历史是线性的!

image

利用getBoundingClientRect判断元素是否在窗口可视范围内

// getBoundingClientRect 方法返回元素的边界,
// window的innerWidth和innerHeight返回当前窗口的实际长宽,不包括标题栏地址栏
var isVisibleInViewport = (function(){
    return function(element, inInsideWindow) {
        var rect = element.getBoundingClientRect();
        var innerWidth = window.innerWidth;
        var innerHeight = window.innerHeight;
        var top = rect.top;
        var left = rect.left;
        var right = rect.right;
        var bottom = rect.bottom;
        if(!inInsideWindow){
            inInsideWindow = false;
        }
        var isInside = false;
        if(inInsideWindow){
            isInside = top >= 0 && left >= 0 && 
                        right <= innerWidth && bottom <= innerHeight;
        }else{
            isInside = ((top >= 0 && top < innerHeight) || 
                            (bottom > 0 && bottom <= innerHeight)) && 
                        ((left >= 0 && left < innerWidth) || 
                            (right > 0 && right <= innerWidth));
        }
        return isInside;
    }
})();

flvjs结构记录

Object.assign的复制对象方法需要注意,该复制行为为浅复制

var d = {"a":1, "b":2, "c":[1, 2, 3]};
var e  = Object.assign({}, d);
d.c.push(4);
console.log(d.c);  //1,2,3,4
console.log(e.c);  //1,2,3,4

输出对象键名问题记录

var logPName = (function(){
    return function(obj, callback) {
        Object.keys(obj).forEach(function(value, key, obj){
            callback(value, key, obj);  //值,键,对象
        });
    }
})();

//example
logPName({"a":1, "b":2, "c":3}, function(key){
	console.log(key); //具体callback接受的参数少于调用的也不要紧,可以通过arguments来获取
});

//针对Object.keys的polyfill问题可参考
//@see http://tokenposts.blogspot.com/2012/04/javascript-objectkeys-browser.html

if (!Object.keys) Object.keys = function(o) {
  if (o !== Object(o))
    throw new TypeError('Object.keys called on a non-object'); //判断是否为对象,注意 !== 符号
  var k=[],p;
  for (p in o) if (Object.prototype.hasOwnProperty.call(o,p)) k.push(p); //利用Object.prototype.hasOwnProperty 来避免原生的hasOwnProperty被覆盖
  return k;
}

Number使用问题记录

var round = (function(){
    return function(d, e){
        return Number(Math.round(Number(d + "e" + e)) + "e-" + e);    
    }
})();

var floor = (function(){
    return function(d, e){
        return Number(Math.floor(Number(d + "e" + e)) + "e-" + e);    
    }
})();

var ceil = (function(){
    return function(d, e){
        return Number(Math.ceil(Number(d + "e" + e)) + "e-" + e);    
    }
})();

判断当前页面是否失去焦点

//参考:https://mokiee.com/code/193
var tabPageVisibilityManager = (function(){
    var hiddenProperty = ["hidden", "webkitHidden", "mozHidden", "msHidden"];
    var len = hiddenProperty.length;
    var propertyKey = "";
    for(var i = 0; i < len; i ++){
        if(hiddenProperty[i] in document){
            propertyKey = hiddenProperty[i]; //获取具体的hidden属性名
            break;
        }
    }
    var eventKey = "";
    if(propertyKey && propertyKey != ""){
        eventKey = propertyKey.replace(/hidden/i, "visibilitychange");
    }
    //获取具体事件名eventKey
    return function(pause_callback, resume_callback) {
        document.addEventListener(eventKey, function(){
            if(!document[propertyKey]){
                if(resume_callback != null){
                    resume_callback();
                }
            }else{
                if(pause_callback != null){
                    pause_callback();
                }
            }
        });
    }
})();

//使用
tabPageVisibilityManager(function(){
    console.log("pause"); //暂停
}, function(){
    console.log("resume"); //恢复
});

jQuery中hasClass的实现问题

//如下实现是对JQuery的hasClass方法进行简化,直接书写成function格式

//获取className, 也可以通过访问元素的className属性来获取
function getClass(elem) {
	return elem.getAttribute && elem.getAttribute("class") || "";
}

//jQuery的实现会判断nodeType是否为1,同时需要注意className和selector的左右
//都被添加了一个空格字符,这是为了后面使用indexOf判断的准确性
function hasClass(elem, selector) {
	var className = " " + selector + " ";
	if(elem){
		if ( elem.nodeType === 1 &&
			( " " + 
stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
				return true;
		}
	}
	return false;
}

//stripAndCollapse中正则表达式中的\x20,就是指的空格键,\x标明数值20是16进制,
//换成十进制就是32
function stripAndCollapse( value ) {
	var tokens = value.match( /[^\x20\t\r\n\f]+/g) || []; 
	return tokens.join( " " );
}
//*************************************************************
//如下是一个简单的实现方法(没有做一些细致的检查)
function hasClass(elem, name){
	return " " + elem.className + " ".indexOf(" " + name + " ") > -1;
}

参考:关于为何需要在className和selector左右添加空格的讨论

利用字符串替换函数拼接html

//利用stringReplace方法可以方便拼接html
var stringReplace = (function(){
        function isArray(arr) {
            return Object.prototype.toString.call(arr) === '[object Array]';
        }
        return function(str){
            var args = [];
            for(var i = 1; i < arguments.length; i ++){
              args.push(arguments[i]);
            }
            var r, provider;
            if (args.length == 1 && typeof(args[0]) == "object" && !isArray(args[0])) {
                r = /\(([a-z]+)\)|\{([a-z]+)\}|\[([a-z]+)\]/gi;
                provider = args[0];
            } else {
                r = /\(\d+\)|\{\d+\}|\[\d+\]/gi;
                if (isArray(args[0])) {
                    provider = args[0];
                } else {
                    provider = args;
                }
            }
            str = str.replace(r, function (match) {
                return provider[match.slice(1, match.length - 1)];
            });
            return str;
        }
})();
其实在es6中已经提供了类似方法,但在老版本js中,可以利用该方法
var demo = '<div class="demo_parent {demo_parent_class}">' + 
                    '<div class="demo_child1 {demo_child1_class}">' + 
                        '<img class="demo_child1_img" src={demo_child1_img_src}>' + 
                    '</div>' + 
                    '<div class="demo_child2 {demo_child2_class}">' + 
                        '<img class="demo_child2_img" src={demo_child2_img_src}>' + 
                     '</div>' + 
                    '<span class="demo_txt {demo_txt_class}">test</span>' + 
                '</div>'
demo = stringReplace(demo, 
                        {"demo_parent_class":"xxx", 
                        "demo_child1_class":"xxx",
                        "demo_child1_img_src": "xxx",
                        "demo_child2_class": "xxx",
                        "demo_child2_img_src": "xxx",
                        "demo_txt_class": "xxx"});
var d = document.createElement("div");
d.innerHTML= demo;

生成随机id

//https://github.com/tejacques/crosstab 参考crosstab库中的实现
var generateId = (function(){
    var pad = function(num, width, paddingStr){
        paddingStr = paddingStr || "0";
        num = num.toString();
        if(num.length >= width){
            return num;
        }
        return new Array((width - num.length) + 1).join(paddingStr) + num;
    }
    var time = function() {
        return new Date().getTime();
    }
    return function(){
        return time().toString() + pad((Math.random() * 0x7FFFFFFF)|0, 10);
    }
})();

//example
var id = generateId(); //

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.