Skip to content

Instantly share code, notes, and snippets.

@chengmu
Last active December 18, 2015 23:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chengmu/5859458 to your computer and use it in GitHub Desktop.
Save chengmu/5859458 to your computer and use it in GitHub Desktop.
《Javascript core and practice》notes
//删除数组中的元素
//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);
};
/*
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());
}
});
//闭包允许访问外部函数的值
//但访问的是该变量最后的值
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());
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
// 通常来讲,函数式编程的谓词(关系运算符,如大于,小于,等于的判断等),以及运算
// (如加减乘数等)都会以函数的形式出现,比如:
// 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));
//模拟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);
});
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"]);
//匿名自执行函数
//函数只需要执行一次,其内部变量无需维护;
//例如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