# 千位分隔符
function commafy(num) {
num = num + '';
var reg = /(-?\d+)(\d{3})/;
while(reg.test(num)) {
num = num.replace(reg, '$1,$2');
}
return num;
}
# jQuery 实现简单 Router
(function($) {
var pathname = location.pathname;
$.route = function() {
$.each(arguments, function(index) {
var path = this["path"];
var func = this["func"];
if(path && func) {
if(pathname.match(path)) {
$(function() {
func.apply(this);
});
}
}
});
};
})(jQuery);
// Example
$.route(
{
// always match
// http://example.com/foo/bar/baz.html
path: /./,
func: function() {
console.log("always match!");
}
},
{
// url contains /sample/index.html
// http://example.com/foo/bar/sample/index.html
path: /\/sample\/index\.html/,
func: function() {
console.log("sample page!");
}
}
);
# 中文输入法截断解决方案
// 利用 compositionstart 和 compositionend 来捕获 IME (input method editor) 的启动和关闭事件
$('#text').on('input', function(e){
if($(this).prop('comStart')) return;
var value = $(this).val();
console.log('当前输入:' + value);
// ....
})
.on('compositionstart', function(e){
$(this).prop('comStart', true);
console.log('中文输入,开始');
})
.on('compositionend', function(e){
$(this).prop('comStart', false);
console.log('中文输入,结束');
});
# jQuery pub/sub 简单实现
(function($) {
var o = $({});
$.subscribe = function() {
o.on.apply(o, arguments);
};
$.unsubscribe = function() {
o.off.apply(o, arguments);
};
$.publish = function() {
o.trigger.apply(o, arguments);
};
}(jQuery));
# 观察者模式
var eventSplitter = /\s+/;
var Events = {
/**
* _callback = {
* tail: [Object],
* next: {
* callback: [Function],
* context: [Object],
* next: {
* callback: [Function],
* context: [Object],
* next: [Object]
* }
* }
* }
*
* 1. 事件列表最顶层存储了一个 tail 对象,它是最后一次绑定的回调事件的 next 的引用;
* 2. evts 允许指定多个事件名,通过空白字符进行分隔(如空格, 制表符等);
* 3. 当事件名称为"all"时, 在调用 fire 方法触发任何事件时,
* 均会调用"all"事件中绑定的所有回调函数;
*/
on: function(evts, callback, context) {
var evt, calls, node, tail, list;
if(!callback) return this;
evts = evts.split(eventSpliter);
calls = this._callbacks || (this._callbacks = {});
while(evt = evts.shift()) {
list = calls[evt];
node = list ? list.tail : {};
node.next = tail = {};
node.callback = callback;
node.context = context;
calls[evt] = {
tail: tail,
next: list ? list.next : node;
}
}
return this;
},
off: function(evts, callback, context) {
var evt, calls, node, tail, cb, ctx;
if(!(calls = this._callbacks)) return this;
if(!(evts || callback || context)) {
delete this._callbacks;
return this;
}
evts = evts ? evts.split(eventSpliter) : Object.key(calls);
while(evt = evts.shift()) {
node = calls[evt];
delete calls[evt];
if(!node || !(callback || context)) continue;
tail = node.tail;
while((node = node.next) !== tail) {
cb = node.callback;
ctx = node.context;
if((callback && cb !== callback) || (context && ctx !== context)) {
this.on(evt, cb, ctx);
}
}
}
return this;
},
fire: function(evts) {
var evt, node, calls, tail, args, all, rest;
if(!(calls = this._callbacks)) return this;
all = calls.all;
evts = evts.split(eventSpliter);
rest = Array.prototype.slice.call(arguments, 1);
while(evt = evts.shift()) {
if(node = calls[evt]) {
tail = node.tail;
while((node = node.next) !== tail) {
node.callback.apply(node.context || this, rest);
}
}
if(node = all) {
tail = node.tail;
args = [evt].concat(rest);
while((node = node.next) !== tail) {
node.callback.apply(node.context || this, args);
}
}
}
return this;
}
}
# 短小强悍的 Javascript 异步调用库
var queue = function(funcs, scope) {
(function next() {
if(funcs.length > 0) {
funcs.shift().apply(scope, [next].concat(Array.prototype.slice.call(arguments, 0)));
}
})();
}
// Example
var obj = { value: null };
queue([
function(callback){
var me = this;
setTimeout(function(){
me.value = 10;
callback(20);
});
},
function(callback, add){
console.log(this.value + add);
callback();
},
function(){
console.log(obj.value);
}
], obj);
# 干掉鼠标右键菜单
function NoRightClick(pid) { // pid: flash's parentNode id
var el = document.getElementById(pid);
if(el.addEventListener) {
el.addEventListener('mousedown',function(event){
if(event.button == 2){
event.stopPropagation(); // for firefox
event.preventDefault(); // for chrome
}
},true);
}
else {
el.attachEvent('onmousedown', function() {
if(event.button == 2) {
el.setCapture();
}
});
el.attachEvent('onmouseup', function() {
el.releaseCapture();
});
el.oncontextmenu = function() {
return false;
};
}
};
# 判断是否是素数
function isPrime(num) {
return n < 2 ? false : !/^(11+?)\1+$/.test(Array(num+1).join(1));
}
# Babel 的 polyfill 和 runtime 的区别
babel-plugin-transform-runtime
: 适用于 JavaScript 库和工具包的实现,避免 babel 编译的工具函数在每个模块里重复出现,减小库和工具包的体积babel-polyfill
: 转译 javascript 新的对象和方法,为当前环境提供一个垫片
总结:
具体项目还是需要使用 babel-polyfill,只使用 babel-runtime 的话,实例方法不能正常工作(例如 "foobar".includes("foo"))
JavaScript 库和工具可以使用 babel-runtime,在实际项目中使用这些库和工具,需要该项目本身提供 polyfill