Ecmascript262-3 1999年,ie5.5及之后彻底支持,ff,chrome等所有支持
Ecmascript262-4 由于跨越太大,废弃
Ecmascript262-3.1 后更名ecmascript5 主流浏览器支持,ie8部分支持,ie9所有支持chrome
1.1 Array.isArray(arg)
若是是数组,放回true数组
if (!Array.isArray) {
Array.prototype.isArray = function(ar) {
return Object.prototype.toString.call(ar) === “[object Array]”
}
}浏览器
1.2 Object.keys(obj)
把obj的全部属性枚举放到数组里返回,顺序取决于for in的顺序,Object.keys不枚举原型链中的属性缓存
if (!Object.keys) {
Object.prototype.keys = function(obj) {
var ar = [];
for (var i in obj) {
if (Object.prototype.hasOwnProperty.call(obj,i) {
ar.push(i);
}
}
return ar;
}
}安全
1.3 FuncProto.bind
fun.bind(thisArg[, arg1[, arg2[, ...]]])
if (!Function.bind) {
Function.prototype.bind = function(context) {
var fn = this,
arg = [];
for (var i = 1, len = arguments.length; i < len; i++) {
arg[i-1] = arguments[i];
}
return function() {
for (var j = 0, len2 = arguments.length; j < len2; j++) {
arg[i++] = arguments[j];
}
fn.apply(context, arg);
}
}
}闭包
1.4 Object.create
Object.create(prototype, [ propertiesObject ])
建立一个对象并返回,让该对象的prototype对象指向参数的对象app
if (!Object.prototype.create) {
Object.prototype.create = (function() {
function fn() {dom
};
var hasown = Object.prototype.hasOwnProperty;
return function(proto, args) {
var obj;
fn.prototype = proto;
obj = new fn();
fn.prototype = null;
if (args) {
for (var i in args) {
if (hasown.call(args, i)) {
obj[i] = args[i];
}
}
}
return obj;ecmascript
}
}())
}函数
关键点是安全:
var _ = function(obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
};
若是参数obj是经过构造函数_new出来的对象,那么直接返回
若是this不是_的对象,说明可能不是经过new _的调用,因此执行
return new _(obj);
最终执行this._wrapped = obj;
当new ConstructorFn(...) 执行时:
1.一个新对象被建立。它继承自ConstructorFn.prototype(newobj.prototype=foo.prototype).
2.构造函数 ConstructorFn 被执行。执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新实例。new ConstructorFn 等同于 new ConstructorFn(), 只能用在不传递任何参数的状况。
3.若是构造函数返回了一个“对象”,那么这个对象会取代整个new出来的结果。若是构造函数没有返回对象,那么new出来的结果为步骤1建立的对象,ps:通常状况下构造函数不返回任何值,不过用户若是想覆盖这个返回值,能够本身选择返回一个普通对象来覆盖。固然,返回数组也会覆盖,由于数组也是对象。
首先判断参数是否为对象或函数,若是不是,返回空对象。
而后判断是否存在原生create,若是有,调用。
若是没有,经过ctor函数,让ctort.prototype = prototype;
var result = new ctor();
ctor.prototype = null;
var baseCreate = function(prototype) {
if (!_.isObject(prototype)) return {};
if (nativeCreate) return nativeCreate(prototype);
Ctor.prototype = prototype;
var result = new Ctor;
Ctor.prototype = null;
return result;
};
var property = function(key) {
return function(obj) {
return obj == null ? void 0 : obj[key];
};
};
生成安全的取对象属性的方法,防止undefined或null取属性值而报错。
关键点:
obj == null ? void 0 : obj[key];
obj == null 其实是一个隐式转换,就是当obj是null或undefined的时候。
==的隐式转换规则,详见Ecmascript: http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.1
若是双方类型一致,对比值:
若是是undefined, true
若是是null, true
若是是number,
若是其中一个是NaN,不相等
若是值相等,相等
+0, -0, 0是相等的。
若是是String,
当两个字符串长度一致,并且对应位置字符一致那么相等。
若是是Boolean
当二者都是true或者false时候相等。
若是是Object
当二者的指针指向一个对象时相等。
若是类型不一致,
null, undefined相等
string,boolean和number比较时候会转换成数字再比较
boolean和其余的比较会转换成number,true1 false 0
Object和string或number比较会先调用toString或valueOf,获得值后在比较。
用于优化回调函数:
1) 绑定上下文context,若是有context,返回绑定context的函数,用于后续操做。若是没有context,直接返回
2)经过客户端传入的argCount决定返回函数的参数个数,防止使用arguments对象,由于在一些旧的v8版本中,使用
arguments会致使函数得不到浏览器优化。
在函数内部建立一个闭包的迭代函数,而后返回一个函数,判断参数,初始化而后调用这个迭代函数。
闭包大体有这么几个做用:避免命名冲突;私有化变量;变量持久化,让函数参数固定值
这里的做用主要就是变量(函数)持久化,好处就是重复调用的时候不须要再从新建立函数,从而提高执行速度。
为何要用两层闭包呢?第一层闭包持久化iterator
函数,调用reduce
和reduceRight
函数避免重复新建函数。第二层闭包保存keys
,index
,length
这些变量。
调用状况以下,以findIndex为例,咱们一个个分析它的函数
对每一个元素根据传入的函数进行计算,若是true,将这个元素放入数组,最后返回数组。
内部仍是先用optimizeCb进行处理函数的绑定和优化,而后执行each,对每一个元素处理。
1.调用values把对象的值转换成数组返回
2.调用indexOf >=0 判断是否在给定的数组(或对象中)
3.使用createIndexFinder生成indexOf方法,关键点有:
1)根据开始index和dir值,生成循环的条件
2)判断是否被查找的元素是否是NaN(obj !== obj),若是是的话,对每一个元素调用isNaN判断是否是NaN,若是有的话,返回true
_.isNaN = function(obj) {
return _.isNumber(obj) && obj !== +obj;
};
通常咱们判断NaN的方法只须要:a !== a,那么就是NaN了。
而这里是为了同时检验出:new Object(NaN)
这个数的类型(toString)是Number,若是+obj的话就转换成了NaN,知足new Object(NaN) !== NaN
另附对象转换成数字:
When the [[DefaultValue]] internal method of O is called with hint Number, the following steps are taken:
valueOf
".toString
".首先调用valueOf,若是可执行,返回值,不然调用toString,返回值。
_.invoke(obj, method)
对obj的每一个元素执行method方法,结果组成数组并返回;
若是method是自定义函数,那么执行method,不然,得到eachvalue[method]并执行。
乱序排列一个数组,几个关键点:
1)返回的是新数组
2)有可能顺序是不变的
3)random的
3)核心是:
if (random !== index) shuffle[index] = shuffle[random]
shuffle[random] = set[index];
给函数设置预约义的变量,容许使用占位符。
核心思想是在partial函数中处理参数,而后返回一个闭包函数,把两部分参数组装在一块儿。
_.throttle(function, wait, [options])
_.after = function(times, func) {
return function() {
if (--times < 1) {
return func.apply(this, arguments);
}
};
};
由于参数也是函数内的一个变量,因此返回的闭包函数对参数的操做也是同一个内存位置,所以直接更新times进行判断。
_.template(templateString, [settings])
var escapes = {
"'": "'",
'\\': '\\',
'\r': 'r',
'\n': 'n',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
2.而后对捕获的内容处理,而后组装成js代码的字符串形式
对全部匹配的正则都作处理,组装成一个大的js代码字符串。
再组装,增长参数定义,经常使用函数定义等内容在前头。
最后使用new Function建立render函数,函数的参数有两个:
第一个参数是传入的变量对象,若是有setting.variable的话,使用这个字符串做为变量名,而后模板中都是用这个变量名调用和访问,速度会快。
若是没有的话,就命名为obj,而后经过with(obj) {函数体}的方式来使用这个传入的数据。