消除代码全局变量名占用: //本质是使用匿名函数;
void function(x, y, z) { console.log(x + y + z); }(1,2,3);
//要使函数内的变量不被释放,需要使用引用;
一次性的构造函数: //维护原型链,保证标识符重写后,实例.constructor仍指向构造器;
var Instance = function() {}; Instance.prototype = { constructor: Instance } Instance = new Instance(); Instance2 = new Instance.constructor();
对象充当识别器: //利用对象实例在全局的唯一性
//判断某个标识符是否存在函数内;
var obj = function() { var yes = {}; var tab = {v1: yes}; return { query: function(id) { return tab[id] === yes} } }(); obj.query('v1'); //true
//判断是外部调用还是内部调用; var myFunc = function() { var handle = {}; function _myFunc() { if(arguments[0] === handle) { console.log('in'); } else { console.log('out'); } } Array.prototype.unshift.apply(arguments,[handle]); _myFunc.apply(null,arguments); return _myFunc; } var func = myFunc(); //in func(); //out
识别构造器调用:
//唯一的问题是如果将构造器赋给实例为方法,则只能判断为new;
function MyObject() { if(this instanceof arguments.callee) { // this.constructor === arguments.callee ;此方法注意维护constructor console.log('new'); } else if(this === window) { console.log('window'); } else { console.log('object'); } } var obj1 = new MyObject(); //new var obj2 = {}; obj2.func = MyObject; obj2.func(); //'object' MyObject(); //'window'
快速调用对象方法: //使用apply,call;
var obj = {}; [].push.apply(obj,[1,2]); console.log(obj); //{0:1,1:2,length:2} ,会传入length;
//判断对象的hasOwnProperty属性是否被重写; var obj = { hasOwnProperty: function() {} }; console.log({}.hasOwnProperty.call(obj, 'hasOwnProperty')); //true
//对String,Boolean,Number直接量使用该技巧,由于其会有隐式包装,所以会多一些开销;
日期计算:
//获取当前对应n天前的时间数据,然后用date的获取方法获取要获取的数据;
var getPrevDay = function (n) { return new Date(new Date() - n*24*60*60*1000); } console.log(getPrevDay(1).getDate());
//获取两天差的时间; var d1 = new Date(2007,1,1,12,1,30,300); var d2 = new Date(2006,10,15); console.log(parseInt((d1-d2)/1000/60/60) + ' h'); console.log(parseInt((d1-d2)/1000/60/60/24) + ' d');
构造复杂对象:
//对象进行值运算;
var obj = {}; obj.valueOf = function() { return 10; } console.log(10 * obj); //100
函数封装为方法:
aObj = {info: 'hello'}; aFunc = function() {console.log(this.info)}; function getMethod(obj, func) { return function() { return func.apply(obj); } } m = getMethod(aObj, aFunc); //建立两者关系的函数 m(); //相当于 m2 = aFunc.bind(aObj); m2();
构造函数参数:
//在当前数组中查找item,找到删除并用插入list,否则在最后插入list
Array.prototype.findAndInsert = function(item, list) { item = this.indexOf(item); this.splice.apply(this, [ item < 0 ? this.length : item, 1].concat(list) ); }
var aPosition = 1, x = 100, y = 200, z = 300; function foo(v1, v2, v3) { var args = function() { return [].splice.call(arguments, aPosition, 0, x, y, z), arguments; // }.apply(this, arguments); console.log([].slice.apply(args)); //[11, 100, 200, 300, 22, 33, findAndInsert] console.log([].slice.apply(arguments)); //[11, 22, 33, findAndInsert] } foo(11,22,33);
利用钩子扩充函数功能:
//基本函数扩充
function myFunc1() { console.log('myFunc1'); } myFunc1 = function(foo) { return function() { console.log('hook'); return foo.apply(this, arguments); } }(myFunc1); myFunc1();
//原型方法扩充
Number.prototype.toString = function(foo) { return function() { var result = foo.apply(this, arguments).toUpperCase(); console.log('hook'); return result; } }(Number.prototype.toString);
//扩充后只执行一次 myFunc2 = function(foo) { return function() { myFunc2 = foo; //脱钩 console.log('hook'); return foo.apply(this, arguments); } }(myFunc2);