Last active
December 18, 2015 23:09
-
-
Save chengmu/5859458 to your computer and use it in GitHub Desktop.
《Javascript core and practice》notes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//删除数组中的元素 | |
//Array Remove - By John Resig (MIT Licensed) | |
Array.prototype.remove = function(from, to) { | |
var rest = this.slice((to || from) + 1 || this.length); | |
this.length = from < 0 ? this.length + from : from; | |
return this.push.apply(this, rest); | |
}; | |
//Array Remove - By John Resig (MIT Licensed) | |
Array.remove = function(array, from, to) { | |
var rest = array.slice((to || from) + 1 || array.length); | |
array.length = from < 0 ? array.length + from : from; | |
return array.push.apply(array, rest); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Base.js, version 1.1a | |
Copyright 2006-2010, Dean Edwards | |
License: http://www.opensource.org/licenses/mit-license.php | |
*/ | |
var Base = function() { | |
// dummy | |
}; | |
Base.extend = function(_instance, _static) { // subclass | |
var extend = Base.prototype.extend; | |
// build the prototype | |
Base._prototyping = true; | |
var proto = new this; | |
extend.call(proto, _instance); | |
proto.base = function() { | |
// call this method from any other method to invoke that method's ancestor | |
}; | |
delete Base._prototyping; | |
// create the wrapper for the constructor function | |
//var constructor = proto.constructor.valueOf(); //-dean | |
var constructor = proto.constructor; | |
var klass = proto.constructor = function() { | |
if (!Base._prototyping) { | |
if (this._constructing || this.constructor == klass) { // instantiation | |
this._constructing = true; | |
constructor.apply(this, arguments); | |
delete this._constructing; | |
} else if (arguments[0] != null) { // casting | |
return (arguments[0].extend || extend).call(arguments[0], proto); | |
} | |
} | |
}; | |
// build the class interface | |
klass.ancestor = this; | |
klass.extend = this.extend; | |
klass.forEach = this.forEach; | |
klass.implement = this.implement; | |
klass.prototype = proto; | |
klass.toString = this.toString; | |
klass.valueOf = function(type) { | |
//return (type == "object") ? klass : constructor; //-dean | |
return (type == "object") ? klass : constructor.valueOf(); | |
}; | |
extend.call(klass, _static); | |
// class initialisation | |
if (typeof klass.init == "function") klass.init(); | |
return klass; | |
}; | |
Base.prototype = { | |
extend: function(source, value) { | |
if (arguments.length > 1) { // extending with a name/value pair | |
var ancestor = this[source]; | |
if (ancestor && (typeof value == "function") && // overriding a method? | |
// the valueOf() comparison is to avoid circular references | |
(!ancestor.valueOf || ancestor.valueOf() != value.valueOf()) && | |
/\bbase\b/.test(value)) { | |
// get the underlying method | |
var method = value.valueOf(); | |
// override | |
value = function() { | |
var previous = this.base || Base.prototype.base; | |
this.base = ancestor; | |
var returnValue = method.apply(this, arguments); | |
this.base = previous; | |
return returnValue; | |
}; | |
// point to the underlying method | |
value.valueOf = function(type) { | |
return (type == "object") ? value : method; | |
}; | |
value.toString = Base.toString; | |
} | |
this[source] = value; | |
} else if (source) { // extending with an object literal | |
var extend = Base.prototype.extend; | |
// if this object has a customised extend method then use it | |
if (!Base._prototyping && typeof this != "function") { | |
extend = this.extend || extend; | |
} | |
var proto = { | |
toSource: null | |
}; | |
// do the "toString" and other methods manually | |
var hidden = ["constructor", "toString", "valueOf"]; | |
// if we are prototyping then include the constructor | |
var i = Base._prototyping ? 0 : 1; | |
while (key = hidden[i++]) { | |
if (source[key] != proto[key]) { | |
extend.call(this, key, source[key]); | |
} | |
} | |
// copy each of the source object's properties to this object | |
for (var key in source) { | |
if (!proto[key]) extend.call(this, key, source[key]); | |
} | |
} | |
return this; | |
} | |
}; | |
// initialise | |
Base = Base.extend({ | |
constructor: function() { | |
this.extend(arguments[0]); | |
} | |
}, { | |
ancestor: Object, | |
version: "1.1", | |
forEach: function(object, block, context) { | |
for (var key in object) { | |
if (this.prototype[key] === undefined) { | |
block.call(context, object[key], key, object); | |
} | |
} | |
}, | |
implement: function() { | |
for (var i = 0; i < arguments.length; i++) { | |
if (typeof arguments[i] == "function") { | |
// if it's a function, call it | |
arguments[i](this.prototype); | |
} else { | |
// add the interface using the extend method | |
this.prototype.extend(arguments[i]); | |
} | |
} | |
return this; | |
}, | |
toString: function() { | |
return String(this.valueOf()); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//闭包允许访问外部函数的值 | |
//但访问的是该变量最后的值 | |
var outer = []; | |
function close(){ | |
var array = [1,2,3,4,5] | |
for (var i = 0; i<array.length;i++){ | |
var x = {}; | |
x.no = i; | |
x.text = array[i]; | |
x.invo = function (no){ | |
return function(){console.log(no)} | |
}(i); | |
//实际上相当于x.invo = function(){console.log(0)}; | |
//这里的no是获取到的参数,而非x对象的属性值 | |
//在这一运行过程中,close所处的上下文是window | |
//在执行一个函数时,函数的参数和局部变量会作为调用对象的属性予以保存 | |
//同时,执行器会为函数创建一个执行上下文(context) | |
//与上下文对应起来的是作用链 | |
//实现为一个链表,每一项都是一个全局对象 | |
outer.push(x); | |
} | |
} | |
close(); | |
console.log(outer[0].invo()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var adder = function(num) { | |
return function(y) { | |
return num + y; | |
} | |
} | |
var inc = adder(1); | |
var dec = adder(-1); | |
//这里的inc/dec 两个变量事实上是两个新的函数,可以通过括号来调用, | |
//inc, dec现在是两个新的函数,作用是将传入的参数值(+/-)1 | |
print(inc(99)); //100 | |
print(dec(101)); //100 | |
print(adder(100)(2)); //102 | |
print(adder(2)(100)); //102 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 通常来讲,函数式编程的谓词(关系运算符,如大于,小于,等于的判断等),以及运算 | |
// (如加减乘数等)都会以函数的形式出现,比如: | |
// a > b | |
// 通常表示为: | |
// gt(a, b)//great than | |
// 因此,可以首先对这些常见的操作进行一些包装,以便于我们的代码更具有“函数式”风格: | |
function abs(x) { | |
return x > 0 ? x : -x; | |
} | |
function add(a, b) { | |
return a + b; | |
} | |
function sub(a, b) { | |
return a - b; | |
} | |
function mul(a, b) { | |
return a * b; | |
} | |
function div(a, b) { | |
return a / b; | |
} | |
function rem(a, b) { | |
return a % b; | |
} | |
function inc(x) { | |
return x + 1; | |
} | |
function dec(x) { | |
return x - 1; | |
} | |
function equal(a, b) { | |
return a == b; | |
} | |
function great(a, b) { | |
return a > b; | |
} | |
function less(a, b) { | |
return a < b; | |
} | |
function negative(x) { | |
return x < 0; | |
} | |
function positive(x) { | |
return x > 0; | |
} | |
function sin(x) { | |
return Math.sin(x); | |
} | |
function cos(x) { | |
return Math.cos(x); | |
} | |
/* 阶乘实例 | |
* product <- counter * product | |
* counter <- counter + 1 | |
* */ | |
function factorial(n) { | |
function fact_iter(product, counter, max) { | |
if (great(counter, max)) { | |
return product; | |
} else { | |
fact_iter(mul(counter, product), inc(counter), max); | |
} | |
} | |
return fact_iter(1, 1, n); | |
} | |
// 函数式风格重构 | |
function factorial(n) { | |
return (function factiter(product, counter, max) { | |
if (great(counter, max)) { | |
return product; | |
} else { | |
return factiter(mul(counter, product), inc(counter), max); | |
} | |
})(1, 1, n); | |
} | |
factorial(10); | |
//Y 结合因子:实现匿名函数的递归调用 | |
(function(x) { | |
return x == 0 ? 1 : x * arguments.callee(x - 1); | |
})(10); //3628800 | |
//函数的不动点 | |
function fixedPoint(fx, first) { | |
var tolerance = 0.00001; | |
function closeEnough(x, y) { | |
return less(abs(sub(x, y)), tolerance) | |
}; | |
function Try(guess) { //try 是javascript中的关键字,因此这个函数名为大写 | |
var next = fx(guess); | |
//print(next+" "+guess); | |
if (closeEnough(guess, next)) { | |
return next; | |
} else { | |
return Try(next); | |
} | |
}; | |
return Try(first); | |
} | |
// 数层嵌套函数, | |
function sqrt(x) { | |
return fixedPoint( | |
function(y) { | |
return function(a, b) { | |
return div(add(a, b), 2); | |
}(y, div(x, y)); | |
}, | |
1.0); | |
} | |
print(sqrt(100)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//模拟map方法 | |
Array.prototype.map = function(func /*, obj */ ) { | |
var len = this.length; | |
//check the argument | |
if (typeof func != "function") { | |
throw new Error("argument should be a function!"); | |
} | |
var res = []; | |
var obj = arguments[1]; | |
for (var i = 0; i < len; i++) { | |
//func.call(), apply the func to this[i] | |
res[i] = func.call(obj, this[i], i, this); | |
} | |
return res; | |
}; | |
function double(x) { | |
return x * 2; | |
} | |
[1, 2, 3, 4, 5].map(double); //return [2, 4, 6, 8, 10] | |
[{ | |
id: "item1" | |
}, { | |
id: "item2" | |
}, { | |
id: "item3" | |
}].map(function(current) { | |
console.log(current.id); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Shape(type) { | |
this.type = type || "rect"; | |
this.calc = function() { | |
return "calc, " + this.type; | |
}; | |
} | |
var triangle = new Shape("triangle"); | |
print(triangle.calc()); | |
var circle = new Shape("circle"); | |
print(circle.calc()); | |
var triangle = new Shape("triangle"); | |
//上一句相当于下面的代码 | |
var triangle = {}; | |
Shape.apply(triangle, ["triangle"]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//匿名自执行函数 | |
//函数只需要执行一次,其内部变量无需维护; | |
//例如UI的初始化 | |
var datamodel = { | |
table : [], | |
tree : {} | |
}; | |
(function(dm){ | |
for(var i = 0; i < dm.table.rows; i++){ | |
var row = dm.table.rows[i]; | |
for(var j = 0; j < row.cells; i++){ | |
drawCell(i, j); | |
} | |
} | |
//build dm.tree | |
})(datamodel); | |
//缓存 | |
//闭包不会释放外部的引用,从而函数内部的值得以保存; | |
var cache = {}, | |
count = []; | |
return { | |
attachSearchBox : function(dsid){ | |
if(dsid in cache){//如果结果在缓存中 | |
return cache[dsid];//直接返回缓存中的对象 | |
} | |
var fsb = new uikit.webctrl.SearchBox(dsid);//新建 | |
cache[dsid] = fsb;//更新缓存 | |
if(count.length > 100){//保正缓存的大小<=100 | |
delete cache[count.shift()]; | |
} | |
return fsb; | |
}, | |
clearSearchBox : function(dsid){ | |
if(dsid in cache){ | |
cache[dsid].clearSelection(); | |
} | |
} | |
}; | |
})(); | |
//实现封装 | |
//外部无法访问其私有变量 | |
//实现面向对象中的对象,不同的对象拥有独立的成员和状态,互不干涉 | |
var person = function(){ | |
//变量作用域为函数内部,外部无法访问 | |
var name = "default"; | |
return { | |
getName : function(){ | |
return name; | |
}, | |
setName : function(newName){ | |
name = newName; | |
} | |
} | |
}(); | |
print(person.name);//直接访问,结果为undefined | |
print(person.getName()); | |
person.setName("abruzzi"); | |
print(person.getName()); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment