js:语言精髓笔记13--语言技巧

消除代码全局变量名占用: //本质是使用匿名函数;

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);
原文地址:https://www.cnblogs.com/jinkspeng/p/4094767.html