const debounce = (fn, delay) => { let timer = null; return (...args) => { clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, args); }, delay); }; };
underscore版本:javascript
_.debounce = function(func, wait, immediate) { var timeout, result; var later = function(context, args) { timeout = null; if (args) result = func.apply(context, args); }; var debounced = restArguments(function(args) { if (timeout) clearTimeout(timeout); if (immediate) { var callNow = !timeout; timeout = setTimeout(later, wait); if (callNow) result = func.apply(this, args); } else { timeout = _.delay(later, wait, this, args); } return result; }); debounced.cancel = function() { clearTimeout(timeout); timeout = null; }; return debounced; };
lodash版本css
import isObject from './isObject.js' import root from './.internal/root.js' function debounce(func, wait, options) { let lastArgs, lastThis, maxWait, result, timerId, lastCallTime let lastInvokeTime = 0 let leading = false let maxing = false let trailing = true const useRAF = (!wait && wait !== 0 && typeof root.requestAnimationFrame === 'function') if (typeof func !== 'function') { throw new TypeError('Expected a function') } wait = +wait || 0 if (isObject(options)) { leading = !!options.leading maxing = 'maxWait' in options maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait trailing = 'trailing' in options ? !!options.trailing : trailing } function invokeFunc(time) { const args = lastArgs const thisArg = lastThis lastArgs = lastThis = undefined lastInvokeTime = time result = func.apply(thisArg, args) return result } function startTimer(pendingFunc, wait) { if (useRAF) { root.cancelAnimationFrame(timerId) return root.requestAnimationFrame(pendingFunc) } return setTimeout(pendingFunc, wait) } function cancelTimer(id) { if (useRAF) { return root.cancelAnimationFrame(id) } clearTimeout(id) } function leadingEdge(time) { lastInvokeTime = time timerId = startTimer(timerExpired, wait) return leading ? invokeFunc(time) : result } function remainingWait(time) { const timeSinceLastCall = time - lastCallTime const timeSinceLastInvoke = time - lastInvokeTime const timeWaiting = wait - timeSinceLastCall return maxing ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting } function shouldInvoke(time) { const timeSinceLastCall = time - lastCallTime const timeSinceLastInvoke = time - lastInvokeTime return (lastCallTime === undefined || (timeSinceLastCall >= wait) || (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)) } function timerExpired() { const time = Date.now() if (shouldInvoke(time)) { return trailingEdge(time) } timerId = startTimer(timerExpired, remainingWait(time)) } function trailingEdge(time) { timerId = undefined if (trailing && lastArgs) { return invokeFunc(time) } lastArgs = lastThis = undefined return result } function cancel() { if (timerId !== undefined) { cancelTimer(timerId) } lastInvokeTime = 0 lastArgs = lastCallTime = lastThis = timerId = undefined } function flush() { return timerId === undefined ? result : trailingEdge(Date.now()) } function pending() { return timerId !== undefined } function debounced(...args) { const time = Date.now() const isInvoking = shouldInvoke(time) lastArgs = args lastThis = this lastCallTime = time if (isInvoking) { if (timerId === undefined) { return leadingEdge(lastCallTime) } if (maxing) { timerId = startTimer(timerExpired, wait) return invokeFunc(lastCallTime) } } if (timerId === undefined) { timerId = startTimer(timerExpired, wait) } return result } debounced.cancel = cancel debounced.flush = flush debounced.pending = pending return debounced } export default debounce
const throttle = (fn, delay = 500) => { let flag = true; return (...args) => { if (!flag) return; flag = false; setTimeout(() => { fn.apply(this, args); flag = true; }, delay); }; };
underscore版本:html
_.throttle = function(func, wait, options) { var timeout, context, args, result; var previous = 0; if (!options) options = {}; var later = function() { previous = options.leading === false ? 0 : _.now(); timeout = null; result = func.apply(context, args); if (!timeout) context = args = null; }; var throttled = function() { var now = _.now(); if (!previous && options.leading === false) previous = now; var remaining = wait - (now - previous); context = this; args = arguments; if (remaining <= 0 || remaining > wait) { if (timeout) { clearTimeout(timeout); timeout = null; } previous = now; result = func.apply(context, args); if (!timeout) context = args = null; } else if (!timeout && options.trailing !== false) { timeout = setTimeout(later, remaining); } return result; }; throttled.cancel = function() { clearTimeout(timeout); previous = 0; timeout = context = args = null; }; return throttled; };
lodash版本:java
import debounce from './debounce.js' import isObject from './isObject.js' function throttle(func, wait, options) { let leading = true let trailing = true if (typeof func !== 'function') { throw new TypeError('Expected a function') } if (isObject(options)) { leading = 'leading' in options ? !!options.leading : leading trailing = 'trailing' in options ? !!options.trailing : trailing } return debounce(func, wait, { leading, trailing, 'maxWait': wait }) } export default throttle
let imgs=document.querySelectorAll('img'); let clientHeight=window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight function lazyLoad(){ let scrollTop=window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; for(let i=0;i<imgs.length;i++){ let x=clientHeight + scrollTop-imgs[i].offsetTop; if(x>0 && x<clientHeight+imgs[i].height){ imgs[i].src=imgs[i].getAttribute('data') } } }
window.onload=function(){ let drag=document.getElementById('box'); drag.onmousedown=function(e){ let e = e || window.event; let diffX=e.clientX-drag.offsetLeft; let diffY=e.clientY-drag.offsetTop; drag.onmousemove=function(e){ let left=e.clientX-diffX; let top=e.clientY-diffY; if(left<0){ left=0; }else if(left>window.innerWidth-drag.offsetWidth){ left=window.innerWidth-drag.offsetWidth; } if(top<0){ top=0; }else if(top>window.innerHeight-drag.offsetHeight){ top=window.innerHeight-drag.offsetHeight } drag.style.left=left+'px'; drag.style.top=top+'px'; } drag.onmouseup=function(e){ this.onmousemove=null; this.onmouseup=null; } } }
function ajax(url,method,fn,type){ return new Promise((resolve,reject)=>{ var xhr=new XMLHttpRequest(); xhr.onreadystatechange=function(){ if(xhr.readyState==4){ if(xhr.status==200){ //var result=xhr.responseText; //fn(result); resolve(JSON.parse(xhr.responseText).count); } } }; xhr.open(method,url+"?"+type,true); if(method=="post"){ xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); } if(method=="get"){ xhr.send(null); }else if(method=="post"){ xhr.send(type); } } ) }
function clone(obj){ let newObj={}; for(let key in obj){ newObj[key]=obj[key]; } return newObj; }
簡版:node
function clone(obj){ if(obj===null){ return null }; if({}.toString.call(obj)==='[object Array]'){ let newArr=[]; newArr=obj.slice(); return newArr; }; let newObj={}; for(let key in obj){ if(typeof obj[key]!=='object'){ newObj[key]=obj[key]; }else{ newObj[key]=clone(obj[key]); } } }
完整版:jquery
const clone = parent => { const isType = (obj, type) => { if (typeof obj !== "object") return false; const typeString = Object.prototype.toString.call(obj); let flag; switch (type) { case "Array": flag = typeString === "[object Array]"; break; case "Date": flag = typeString === "[object Date]"; break; case "RegExp": flag = typeString === "[object RegExp]"; break; default: flag = false; } return flag; }; const getRegExp = re => { var flags = ""; if (re.global) flags += "g"; if (re.ignoreCase) flags += "i"; if (re.multiline) flags += "m"; return flags; }; const parents = []; const children = []; const _clone = parent => { if (parent === null) return null; if (typeof parent !== "object") return parent; let child, proto; if (isType(parent, "Array")) { child = []; } else if (isType(parent, "RegExp")) { child = new RegExp(parent.source, getRegExp(parent)); if (parent.lastIndex) child.lastIndex = parent.lastIndex; } else if (isType(parent, "Date")) { child = new Date(parent.getTime()); } else { proto = Object.getPrototypeOf(parent); child = Object.create(proto); } const index = parents.indexOf(parent); if (index != -1) { return children[index]; } parents.push(parent); children.push(child); for (let i in parent) { child[i] = _clone(parent[i]); } return child; }; return _clone(parent); };
function deepFreeze(object){ let propNames=Object.getOwnPropertyNames(object); for(let name of propNames){ let value=object[name]; object[name]=value && typeof value === 'object' ? deepFreeze(value) : value; } return Object.freeze(object); }
function deepCompare(a,b){ if(a===null || typeof a!=='object' || b===null || typeof b!=='object'){ return a===b } const propsA=Object.getOwnPropertyDescriptors(a); const propsB=Object.getOwnPropertyDescriptors(b); if(Object.keys(propsA).length!==Object.keys(propsB).length){ return false } return Object.keys(propsA).every( key=>deepCompare(a[key],b[key]) ) }
簡版css3
function parseQueryString(url){ let search=url.split('?')[1]; let strs=search.split('&'); let params={}; for(let str of strs){ let arr=str.split('='); params[arr[0]]=isNaN(arr[1])?arr[1]:Number(arr[1]); } return params; }
完整版web
function parseParam(url) { const paramsStr = /.+\?(.+)$/.exec(url)[1]; const paramsArr = paramsStr.split('&'); let paramsObj = {}; paramsArr.forEach(param => { if (/=/.test(param)) { let [key, val] = param.split('='); val = decodeURIComponent(val); val = /^\d+$/.test(val) ? parseFloat(val) : val; if (paramsObj.hasOwnProperty(key)) { paramsObj[key] = [].concat(paramsObj[key], val); } else { paramsObj[key] = val; } } else { paramsObj[param] = true; } }) return paramsObj; }
考慮深度集合ajax
function parse(str){ return str.split('&').reduce((o,kv)=>{ const [key,value]=kv.split('='); if(!value){ return o } deep_set(o,key.split(/[\[\]]/g).filter(x=>x),value); return o },{}) } function deep_set(o,path,value){ let i=0; for(;i<path.length-1;i++){ if(o[path[i]]===undefined){ if(path[i+1].match(/^\d+$/)){ o[path[i]]=[] }else{ o[path[i]]={} } } o=o[path[i]] } o[path[i]]=decodeURIComponent(value) }
let obj={}; Object.defineProperty(obj,Symbol.iterator,{ enumerable:false, writable:false, configurable:true, value:function(){ let o=this; let idx=0; let ks=Object.keys(o); return { next:function(){ return { value:o[ks[idx++]], done:(idx>ks.length) } } } } })
推薦算法
let str='helloworld'; let dict={}; for(let i=0;i<str.length;i++){ if(dict[str[i]]===undefined){ dict[str[i]]=1; }else{ dict[str[i]]+=1; } }
function GetBytes(str){ var len = str.length; var bytes = len; for(var i=0; i<len; i++){ if (str.charCodeAt(i) > 255) bytes++; } return bytes; }
let str = "abcabcabcbbccccc"; let num = 0; let char = ''; str = str.split('').sort().join(''); let re = /(\w)\1+/g; str.replace(re,($0,$1) => { if(num < $0.length){ num = $0.length; char = $1; } }); console.log(`字符最多的是${char},出現了${num}次`);
a='34';b='1234567'; // 返回 2 a='35';b='1234567'; // 返回 -1 a='355';b='12354355'; // 返回 5 isContain(a,b); function isContain(a, b) { for (let i in b) { if (a[0] === b[i]) { let tmp = true; for (let j in a) { if (a[j] !== b[~~i + ~~j]) { tmp = false; } } if (tmp) { return i; } } } return -1; }
var arr=str.split(''); var newArr=[]; for(var i=0;i<arr.length;i++){ newArr[i]=arr[arr.length-i-1]; } var newStr=newArr.join('') console.log(str0);
var newStr=''; for(var i=0;i<str.length;i++){ newStr+=str.charAt(str.length-i-1); } console.log(newStr);
var newStr=str.split("").reverse().join(""); console.log(newStr);
var arr=str.split(''); var obj=Array.from(new Set([...arr])); var newStr=''; for(i of obj){ newStr+=obj[arr.length-i]; } console.log(newStr)
var arr=str.split(''); var newArr=[]; while(arr.length>0){ newArr.push(arr.pop()) }; var newStr=newArr.join(""); console.log(newStr)
function h_str(str,M){ return [...str].reduce((hash,c)=>{ hash=(31*hash+c.charCodeAt(0))%M return hash },0) }
推薦
let dict={}, result=[], j=0; for(let i=0;i<arr.length;i++){ dict[arr[i]]=1; } for(result[j++] in dict);
var newArr=Array.from(new Set(arr)); console.log(newArr);
for(var i=0;i<arr.length;i++){ for(j=i+1;j<arr.length;j++){ if(arr[i]==arr[j]){ arr.splice(j,1); j--; } } } console.log(arr);
var newArr=[]; for(var i=0;i<arr.length;i++){ if(newArr.indexOf(arr[i])===-1){ newArr.push(arr[i]) } } console.log(newArr);
var arr=arr.sort(); var newArr=[arr[0]]; for(var i=1;i<arr.length;i++){ if(arr[i]!==arr[i-1]){ newArr.push(arr[i]) } } console.log(newArr);
var newArr=[]; var obj={}; for(var i=0;i<arr.length;i++){ if(!obj[arr[i]]){ newArr.push(arr[i]); obj[arr[i]]=1 }else{ obj[arr[i]]++ } } console.log(newArr);
var newArr=[]; for(var i=0;i<arr.length;i++){ if(!newArr.includes(arr[i])){//檢測數組是否有某個值 newArr.push(arr[i]); } } console.log(newArr);
var obj={}; var newArr=arr.filter((item,index,arr)=>{ return obj.hasOwnProperty(typeof item+item)?false:(obj[typeof item+item]=true) }) console.log(arrM6);
arr.sort(function(a,b){ return a-b; }) function loop(index){ if(index>=1){ if(arr[index]===arr[index-1]){ arr.splice(index,1); } loop(index-1) } } loop(arr.length-1); console.log(arr);
var map=new Map(); var newArr=[]; for(var i=0;i<arr.length;i++){ if(map.has(arr[i])){ map.set(arr[i],true); }else{ map.set(arr[i],false); newArr.push(arr[i]); } } console.log(newArr);
arr=arr.reduce((prev,cur)=>prev.includes(cur)?prev:[...prev,cur],[]); console.log(arr);
var newArr=[...new Set(arr)]; console.log(newArr);
const compose =(...args)=>args.reduce((prev,current)=>(...values)=>prev(current(...values)));
function rotate(nums, k) { for (let i = 0;i < k; i++) { nums.unshift(nums.pop()); } };
function binary_value(val){ const farr=new Float32Array(1) farr[0]=val const intBytes=new Int8Array(farr.buffer) const view=new DataView(intBytes.buffer) return view.getUnit32() } k=>binary_value(k)%M
function parseToMoney(num) { num = parseFloat(num.toFixed(3)); let [integer, decimal] = String.prototype.split.call(num, '.'); integer = integer.replace(/\d(?=(\d{3})+$)/g, '$&,'); return integer + '.' + (decimal ? decimal : ''); }
function parseToMoney(str){ let re = /(?=(?!\b)(\d{3})+$)/g; return str.replace(re,','); }
function isPhone(tel) { var regx = /^1[34578]\d{9}$/; return regx.test(tel); }
function isEmail(email) { var regx = /^([a-zA-Z0-9_\-])+@([a-zA-Z0-9_\-])+(\.[a-zA-Z0-9_\-])+$/; return regx.test(email); }
function isCardNo(number) { var regx = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/; return regx.test(number); }
const curry=(fn,arr=[])=>(...args)=>( arg=>arg.length===fn.length ? fn(...arg) : curry(fn,arg) )([...arr,...args])
const unCurrying=(fn)=>{ return (...args)=>{ return fn.call(...args); } }
遞歸
function flatten(arr){ return [].concat( ...arr.map(x=>Array.isArray(x)?flatten(x):x) ) }
遞歸,能夠用for去展平拿到想要的第幾項,能夠忽略後續的非展平項,保證性能
function *flatten(arr){ for(let i=0;i<arr.length;i++){ if(Array.isArray(arr[i])){ yield * flatten(arr[i]) }else{ yield arr[i] } } }
堆棧實現非遞歸
function *flatten(arr){ let stack=arr.slice.reverse(); while(stack.length){ const item=stack.pop(); if(item.constructor===Array){ stack=stack.concat(item) }else{ yield item } } }
function isPalindrome(str) { str = str.replace(/\W/g, '').toLowerCase(); return (str == str.split('').reverse().join('')); }
Array.myIsArray=function(o){ return Object.prototype.toString.call(Object(o)) === '[object Array]' }
function isContain(a, b) { for (let i in b) { if (a[0] === b[i]) { let tmp = true; for (let j in a) { if (a[j] !== b[~~i + ~~j]) { tmp = false; } } if (tmp) { return i; } } } return -1; }
function isNegZero(n){ n=Number(n); return (n === n) && (1/n === -Infinity) }
Object.is=function(v1,v2){ if(v1===0 && v2===0){ return 1/v1 === 1/v2; } if(v1!==v1){ return v2!==v2; } return v1 === v2; }
class EventEmitter { constructor() { this._events = this._events || new Map(); this._maxListeners = this._maxListeners || 10; } } EventEmitter.prototype.emit = function(type, ...args) { let handler; handler = this._events.get(type); if (args.length > 0) { handler.apply(this, args); } else { handler.call(this); } return true; }; EventEmitter.prototype.addListener = function(type, fn) { if (!this._events.get(type)) { this._events.set(type, fn); } }; EventEmitter.prototype.emit = function(type, ...args) { let handler; handler = this._events.get(type); if (Array.isArray(handler)) { for (let i = 0; i < handler.length; i++) { if (args.length > 0) { handler[i].apply(this, args); } else { handler[i].call(this); } } } else { if (args.length > 0) { handler.apply(this, args); } else { handler.call(this); } } return true; }; EventEmitter.prototype.addListener = function(type, fn) { const handler = this._events.get(type); if (!handler) { this._events.set(type, fn); } else if (handler && typeof handler === "function") { this._events.set(type, [handler, fn]); } else { handler.push(fn); } }; EventEmitter.prototype.removeListener = function(type, fn) { const handler = this._events.get(type); if (handler && typeof handler === "function") { this._events.delete(type, fn); } else { let position; for (let i = 0; i < handler.length; i++) { if (handler[i] === fn) { position = i; } else { position = -1; } } if (position !== -1) { handler.splice(position, 1); if (handler.length === 1) { this._events.set(type, handler[0]); } } else { return this; } } };
簡版
class EventEmitter{ constructor(){ this._events={}; } on(type,listener){ let listeners=this._events[type]; if(listeners){ listeners.push(listener) }else{ this._events[type]=[listener]; } } emit(type){ let listeners=this._events[type]; let args=Array.from(arguments).slice(1); listeners.forEach(listener=>listener(...args)); } }
var Writable = require('stream').Writable; var util = require('util'); function MyWritable(options) { Writable.call(this, options); } // 構造函數 util.inherits(MyWritable, Writable); // 繼承自Writable MyWritable.prototype._write = function(chunk, encoding, callback) { console.log("被寫入的數據是:", chunk.toString()); // 此處可對寫入的數據進行處理 callback(); }; process.stdin.pipe(new MyWritable()); // stdin做爲輸入源,MyWritable做爲輸出源
function instance_of(L, R) { var O = R.prototype; L = L.__proto__; while (true) { if (L === null) return false; if (O === L) return true; L = L.__proto__; } }
function _new(P){ let o={}; let arg=Array.prototype.slice.call(arguments,1); o.__proto__=P.prototype; P.apply(o,arg); return o; }
function myExtends(sourceObj,targetObj){ for(let key in sourceObj){ if(!(key in targetObj)){ targetObj[key]=sourceObj[key]; } } return targetObj; }
Function.prototype.myCall = function(context) { context.fn = this; let args = []; for (let i = 1, len = arguments.length; i < len; i++) { args.push(arguments[i]); } context.fn(...args); let result = context.fn(...args); delete context.fn; return result; };
Function.prototype.myapply = function(context, arr) { var context = Object(context) || window; context.fn = this; var result; if (!arr) { result = context.fn(); } else { var args = []; for (var i = 0, len = arr.length; i < len; i++) { args.push("arr[" + i + "]"); } result = eval("context.fn(" + args + ")"); } delete context.fn; return result; };
if (!Function.prototype.bind) { Function.prototype.bind = function(oThis) { if (typeof this !== 'function') { throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function() {}, fBound = function() { return fToBind.apply(this instanceof fBound ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); }; if (this.prototype) { fNOP.prototype = this.prototype; } fBound.prototype = new fNOP(); return fBound; }; }
function create(proto) { function F() {} F.prototype = proto; return new F(); }
if(!Function.prototype.softBind){ Function.prototype.softBind=function(obj){ let fn=this; let curried=[].slice.call(arguments,1); let bound=function(){ return fn.apply( (!this || this===(window || global))?obj:this, curried.concat.apply(curried,arguments) ); }; bound.prototype=Object.create(fn.prototype); return bound; } }
Object.prototype.mysuper = function(){ var caller = arguments.callee.caller, name; for(var i in this){ if(this[i] === caller){ name = i; break; } } __proto = this.__proto__ || this.constructor.prototype; try{ return __proto[name].apply(this, arguments); }catch(e){ alert(name + ' is undefined.'); } }
function create(proto) { function F() {} F.prototype = proto; return new F(); }
function Parent(name) { this.parent = name } Parent.prototype.say = function() { console.log(`${this.parent}: 你打籃球的樣子像kunkun`) } function Child(name, parent) { Parent.call(this, parent) this.child = name } Child.prototype = Object.create(Parent.prototype); Child.prototype.say = function() { console.log(`${this.parent}好,我是練習時長兩年半的${this.child}`); } Child.prototype.constructor = Child; var parent = new Parent('father'); parent.say(); var child = new Child('cxk', 'father'); child.say();
function setRem(){ let doc=document.documentElement; let width=doc.getBoundingClientRect().width; let rem=width/75; doc.style.fontSize=rem+'px' } addEventListener('resize',setRem)
let arrayProto=Array.prototype; let proto=Object.create(arrayProto); ['push','unshift','splice','reverse','sort','shift','pop'].forEach(method=>{ proto[method]=function(...args){ let inserted; switch(method){ case 'push': case 'unshift': inserted=args break; case 'splice': inserted = args.slice(2); default: break; } ArrayObserver(inserted); arrayProto[method].call(this,...args) } }) function ArrayObserver(obj){ for(let i=0;i<obj.length;i++){ let item=obj[i]; observer(item); } } function observer(obj){ if(typeof obj !== 'object' || obj == null){ return obj; } if(Array.isArray(obj)){ Object.setPrototypeOf(obj,proto) ArrayObserver(obj); }else{ for (let key in obj){ defineReactive(obj,key,obj[key]) } } } function defineReactive(obj,key,value){ observer(value); // 遞歸建立 get(){ return value; }, set(newValue){ if(value!==newValue){ observer(newValue); value=newValue; } } }
const path=require('path'); const fs=require('fs'); const vm=require('vm'); function Module(id){ this.id=id; this.exports={};//模塊的結果 } Module.wrapper=[ '(function(exports,module,require,__filename,__dirname){' , '})' ] //靜態方法 Module._extensions={ '.js'(module){//js須要將exports傳給用戶 用戶本身解析 let script=fs.readFileSync(module.id,'utf8'); let fnStr=Module.wrapper[0]+script+Module.wrapper[1]; let fn=vm.runInThisContext(fnStr);//讓字符串執行js代碼 //第一個參數改變this指向 module module.exports fn.call(module.exports,module,module.exports,req,module.id,path.dirname(module.id)); }, '.json'(module){ let script=fs.readFileSync(module.id,'utf8'); module.exports=JSON.parse(script) } } //給你一個相對路徑 解析成絕對路徑 Module.resolveFileName=function(filename){ // 1) 把相對路徑轉化爲絕對路徑 默認會先判斷一下是不是絕對路徑 let absPath=path.resolve(__dirname,filename); let flag=fs.existsSync(absPath);//判斷文件是否存在 異步方法被廢棄 let current=absPath; //默認是當前路徑 if(!flag){ let keys=Object.keys(Module._extensions); for(let i=0;i<keys.length;i++){ current=absPath+keys[i];//當前找到的文件路徑 flag=fs.existsSync(current); if(flag){ break; }else{ current=null; } } } if(!current){ // 若是沒有 說明加了後綴文件仍是不存在 throw new Error('文件不存在') } return current; } Module.prototype.load=function(){ //模塊加載就是讀取文件的內容 let ext =path.extname(this.id); Module._extensions[ext](this);//根據不一樣的路徑處理不一樣的方法 } Module._cache={}; function req(filename){ //本身實現了一個require方法 let current=Module.resolveFileName(filename); if(Module._cache[current]){ return Module._cache[current].exports; } let module=new Module(current); Module._cache[current]=module; module.load(); return module.exports; }
const crypto = require('crypto'); function encode(payload, key) { let header = { type: 'JWT', alg: 'sha256' };//聲明類型和算法 var segments = [];//聲明一個數組 segments.push(base64urlEncode(JSON.stringify(header)));//對header進行base64 segments.push(base64urlEncode(JSON.stringify(payload)));//對負載進行base64 segments.push(sign(segments.join('.'), key));//加入簽名 return segments.join('.'); } function sign(input, key) { return crypto.createHmac('sha256', key).update(input).digest('base64'); } function decode(token, key) { var segments = token.split('.'); var headerSeg = segments[0]; var payloadSeg = segments[1]; var signatureSeg = segments[2]; var header = JSON.parse(base64urlDecode(headerSeg)); var payload = JSON.parse(base64urlDecode(payloadSeg)); if (signatureSeg != sign([headerSeg, payloadSeg].join('.'), key)) { throw new Error('verify failed'); } if (payload.exp && Date.now() > payload.exp * 1000) { throw new Error('Token expired'); } return payload; } function base64urlEncode(str) { return new Buffer(str).toString('base64'); } function base64urlDecode(str) { return new Buffer(str, 'base64').toString(); } module.exports = { encode, decode }
// bindActionCreator export default function bindActionCreator(actions,dispatch){ let newActions={}; for(let key in actions){ newActions[key]=()=>dispatch(actions[key].apply(null,arguments)); } return newActions; } // combineReducers export default combineReducers=reducers=>(state={},action)=>Object.keys(reducers).reduce((currentState,key)=>{ currentState[key]=reducers[key](state[key],action); return currentState; },{}); // createStore export default function createStore(reducer,enhancer){ if(typeof enhancer !== 'undefined'){ return enhancer(createStore)(reducer); } let state=null; const listeners=[]; const subscribe=(listener)=>{ listeners.push(listener); } const getState=()=>state; const dispatch=(action)=>{ state=reducer(state,action); listeners.forEach((listener)=>listener()) }; dispatch({}); return {getState,dispatch,subscribe} } // applyMiddleware export default function applyMiddleware(...middlewares){ return (createStore)=>(reducer)=>{ const store=createStore(reducer); let dispatch=store.dispatch; let chain=[]; const middlewareAPI={ getState:store.getState, dispatch:(action)=>dispatch(action) } chain=middlewares.map(middleware=>middleware(middlewareAPI)); dispatch=compose(...chain)(store.dispatch); return { ...store, dispatch } } } // compose export default function compose(...funcs){ return funcs.reduce((a,b)=>(...args)=>a(b(...args))); }
class Route{ constructor(){ this.routes={}; this.currentHash=''; this.freshRoute=this.freshRoute.bind(this); window.addEventListener('load',this.freshRoute,false); window.addEventListener('hashchange',this.freshRoute,false); } storeRoute(path,cb){ this.routes[path]=cb || function(){} } freshRoute(){ this.currentHash=location.hash.slice(1) || '/'; this.routes[this.currentHash]() } }
完整版
const PENDING='pending'; const FULFILLED='fulfilled'; const REJECTED='rejected'; function MyPromise(fn){ const self=this; self.value=null; self.error=null; self.status=PENDING; self.onFulfilledCallbacks=[]; self.onRejectedCallbacks=[]; function resolve(value){ if(value instanceof MyPromise){ return value.then(resolve,reject); } if(self.status===PENDING){ setTimeout(()=>{ self.status=FULFILLED; self.value=value; self.onFulfilledCallbacks.forEach((callback)=>callback(self.value)); },0) } } function reject(error){ if(self.status===PENDING){ setTimeout(function(){ self.status=REJECTED; self.error=error; self.onRejectedCallbacks.forEach((callback)=>callback(self.error)) },0) } } try{ fn(resolve,reject); }catch(e){ reject(e); } } function resolvePromise(bridgepromise,x,resolve,reject){ if(bridgepromise===x){ return reject(new TypeError('Circular reference')); } let called=false; if(x instanceof MyPromise){ if(x.status===PENDING){ x.then(y=>{ resolvePromise(bridgepromise,y,resolve,reject) },error=>{ reject(error); }) }else{ x.then(resolve,reject) } }else if(x!=null && ((typeof x === 'object') || (typeof x === 'function'))){ try{ let then=x.then; if(typeof then === 'function'){ then.call(x,y=>{ if(called) return; called=true; resolvePromise(bridgepromise,y,resolve,reject) },error=>{ if(called) return; called=true; reject(error); }) }else{ resolve(x); } }catch(e){ if(called) return; called=true; reject(e); } }else{ resolve(x); } } MyPromise.prototype.then=function(onFulfilled,onRejected){ const self=this; let bridgePromise; onFulfilled=typeof onFulfilled==='function'?onFulfilled:value=>value; onRejected=typeof onRejected==='function'?onRejected:error=>{throw error}; if(self.status===FULFILLED){ return bridgePromise=new MyPromise((resolve,reject)=>{ setTimeout(()=>{ try{ let x=onFulfilled(self.value); resolvePromise(bridgePromise,x,resolve,reject); }catch(e){ reject(e); } },0) }) } if(self.status===REJECTED){ return bridgePromise=new MyPromise((resolve,reject)=>{ setTimeout(()=>{ try{ let x=onRejected(self.error); resolvePromise(bridgePromise,x,resolve,reject); }catch(e){ reject(e); } },0) }) } if(self.status===PENDING){ return bridgePromise=new MyPromise((resolve,reject)=>{ self.onFulfilledCallbacks.push((value)=>{ try{ let x=onFulfilled(value); resolvePromise(bridgePromise,x,resolve,reject) }catch(e){ reject(e); } }); self.onRejectedCallbacks.push((error)=>{ try{ let x=onRejected(error); resolvePromise(bridgePromise,x,resolve,reject); }catch(e){ reject(e); } }); }); } } MyPromise.prototype.catch=function(onRejected){ return this.then(null,onRejected); } MyPromise.deferred=function(){ let defer={}; defer.promise=new MyPromise((resolve,reject)=>{ defer.resolve=resolve; defer.reject=reject; }); return defer; } try{ module.exports=MyPromise; }catch(e){}
簡版
function myPromise(constructor){ let self=this; self.status='pending'; self.vlaue=undefined; self.reason=undefined; function resolve(value){ if(self.status==='pending'){ self.value=value; self.status='resolved'; } } function reject(reason){ if(self.status==='pending'){ self.reason=reason; self.status='rejected'; } } try{ constructor(resolve,reject); }catch(e){ reject(e); } } myPromise.prototype.then=function(onFullfilled,onRejected){ let self=this; switch(self.status){ case 'resolved': onFullfilled(self.value); break; case 'rejected': onRejected(self.reason); break; default: } }
function run(gen){ let args=[].slice.call(arguments,1), it; it=gen.apply(this,args); return Promise.resolve().then(function handleNext(value){ let next =it.next(value); return (function handleResult(next){ if(next.done){ return next.value; }else{ return Promise.resolve(next.value).then( handleNext, function handleErr(err){ return Promise.resolve( if.throw(err) ).then(handleResult); } ); } })(next); }) }
function promisify(fn){ return function(...args){ return new Promise(function(resolve,reject){ fn(...args,function(err,data){ if(err){ reject(err) }else{ resolve(data); } }; }); } }
function thunkify(fn){ let args=[].slice.call(arguments,1); return function(cb){ args.push(cb); return fn.apply(null,args); } }
setTimeout(function(){ setTimeout(arguments.callee,500) },500)
var json = '{"name":"cxk", "age":25}'; var obj = eval("(" + json + ")");
function jsonStringify(obj){ let type=typeof obj; if(type !== 'object' || type === null){ if(/string|undefined|function/.test(type)){ obj='"'+obj+'"'; } return String(obj); }else{ let json=[]; arr=(obj && obj.constructor===Array); for(let k in obj){ let v=obj[k]; let type=typeof v; if(/string|undefined|function/.test(type)){ v='"'+v+'"'; }else if(type === 'object'){ v=jsonStringify(v); } json.push((arr ? "":'"'+k'":')+String(v)); } return (arr ? "[" : "{" ) + String(json)+(arr ? "]" : "}" ) } }
function indexOf(arr,elem,fromi){ fromi=fromi||0; for(var i=fromi;i<arr.length;i++){ if(elem===arr[i]){ return i; } } return -1; }
簡版:
Array.prototype.myReduce=function(fn,initialValue){ if(this.length===0){ if(initialValue===undefined){ console.error("reduce of empty array with no initialValue") }else{ return initialValue } }else{ let prev=initialValue !== undefined ? initialValue : this[0]; let startIndex = initialValue !== undefined ? 0 : 1; for(let i=startIndex;i<this.length;i++){ prev = fn(prev,this[i]); } return prev; } }
完整版:
Array.prototype.myreduce=function reduce(callbackfn){ const o=this, len=o.length; let k=0, accumulator=undefined, kPresent=false, initialValue=arguments.length>1?arguments[1]:undefined; if(typeof callbackfn !== 'function'){ throw new TypeError(callbackfn+'is not a function'); } if(len === 0 && arguments.length<2){ throw new TypeError('Reduce of empty array with no initial value'); } if(arguments.length>1){ accumulator=initialValue; }else{ accumulator=o[k]; ++k; } while(k<len){ kPresent=o.hasOwnProperty(k); if(kPresent){ const kValue=o[k]; accumulator=callbackfn.apply(undefined,[accumulator,kValue,k,o]); } ++k; } return accumulator; }
function trim(str){ if(str && typeof str==='string'){ return str.replace(/^\s+l\s+$/g/,'') } }
function join(arr,connector){ let str=''; for(let i=0;i<arr.length;i++){ if(i>0){ str+=connector; } if(arr[i] !== undefined){ str+=arr[i]; } } return str; }
function render(template, data) { const reg = /\{\{(\w+)\}\}/; if (reg.test(template)) { const name = reg.exec(template)[1]; template = template.replace(reg, data[name]); return render(template, data); } return template; }
function camelCase(str){ return str.replace(/-\w/g,function(newStr){ return newStr.slice(1).toUpperCase(); }) }
// 實現一個utils方法庫 const _ = exports _.setAttr = function setAttr (node, key, value) { switch (key) { case 'style': node.style.cssText = value break; case 'value': let tagName = node.tagName || '' tagName = tagName.toLowerCase() if ( tagName === 'input' || tagName === 'textarea' ) { node.value = value } else { // 若是節點不是 input 或者 textarea, 則使用 `setAttribute` 去設置屬性 node.setAttribute(key, value) } break; default: node.setAttribute(key, value) break; } } _.slice = function slice (arrayLike, index) { return Array.prototype.slice.call(arrayLike, index) } _.type = function type (obj) { return Object.prototype.toString.call(obj).replace(/\[object\s|\]/g, '') } _.isArray = function isArray (list) { return _.type(list) === 'Array' } _.toArray = function toArray (listLike) { if (!listLike) return [] let list = [] for (let i = 0, l = listLike.length; i < l; i++) { list.push(listLike[i]) } return list } _.isString = function isString (list) { return _.type(list) === 'String' } _.isElementNode = function (node) { return node.nodeType === 1 } // 實現一個 Element import _ from './utils' /** * @class Element Virtrual Dom * @param { String } tagName * @param { Object } attrs Element's attrs, 如: { id: 'list' } * @param { Array <Element|String> } 能夠是Element對象,也能夠只是字符串,即textNode */ class Element { constructor(tagName, attrs, children) { // 若是隻有兩個參數 if (_.isArray(attrs)) { children = attrs attrs = {} } this.tagName = tagName this.attrs = attrs || {} this.children = children // 設置this.key屬性,爲了後面list diff作準備 this.key = attrs ? attrs.key : void 0 } render () { let el = document.createElement(this.tagName) let attrs = this.attrs for (let attrName in attrs) { // 設置節點的DOM屬性 let attrValue = attrs[attrName] _.setAttr(el, attrName, attrValue) } let children = this.children || [] children.forEach(child => { let childEl = child instanceof Element ? child.render() // 若子節點也是虛擬節點,遞歸進行構建 : document.createTextNode(child) // 如果字符串,直接構建文本節點 el.appendChild(childEl) }) return el } } function el (tagName, attrs, children) { return new Element(tagName, attrs, children) } module.exports = el; // 實現 diff 算法 /** * Diff two list in O(N). * @param {Array} oldList - 原始列表 * @param {Array} newList - 通過一些操做的得出的新列表 * @return {Object} - {moves: <Array>} * - moves list操做記錄的集合 */ function diff (oldList, newList, key) { let oldMap = getKeyIndexAndFree(oldList, key) let newMap = getKeyIndexAndFree(newList, key) let newFree = newMap.free let oldKeyIndex = oldMap.keyIndex let newKeyIndex = newMap.keyIndex // 記錄全部move操做 let moves = [] // a simulate list let children = [] let i = 0 let item let itemKey let freeIndex = 0 // newList 向 oldList 的形式靠近進行操做 while (i < oldList.length) { item = oldList[i] itemKey = getItemKey(item, key) if (itemKey) { if (!newKeyIndex.hasOwnProperty(itemKey)) { children.push(null) } else { let newItemIndex = newKeyIndex[itemKey] children.push(newList[newItemIndex]) } } else { let freeItem = newFree[freeIndex++] children.push(freeItem || null) } i++ } let simulateList = children.slice(0) // 移除列表中一些不存在的元素 i = 0 while (i < simulateList.length) { if (simulateList[i] === null) { remove(i) removeSimulate(i) } else { i++ } } // i => new list // j => simulateList let j = i = 0 while (i < newList.length) { item = newList[i] itemKey = getItemKey(item, key) let simulateItem = simulateList[j] let simulateItemKey = getItemKey(simulateItem, key) if (simulateItem) { if (itemKey === simulateItemKey) { j++ } else { // 若是移除掉當前的 simulateItem 可讓 item在一個正確的位置,那麼直接移除 let nextItemKey = getItemKey(simulateList[j + 1], key) if (nextItemKey === itemKey) { remove(i) removeSimulate(j) j++ // 移除後,當前j的值是正確的,直接自加進入下一循環 } else { // 不然直接將item 執行 insert insert(i, item) } } // 若是是新的 item, 直接執行 inesrt } else { insert(i, item) } i++ } // if j is not remove to the end, remove all the rest item // let k = 0; // while (j++ < simulateList.length) { // remove(k + i); // k++; // } // 記錄remove操做 function remove (index) { let move = {index: index, type: 0} moves.push(move) } // 記錄insert操做 function insert (index, item) { let move = {index: index, item: item, type: 1} moves.push(move) } // 移除simulateList中對應實際list中remove掉節點的元素 function removeSimulate (index) { simulateList.splice(index, 1) } // 返回全部操做記錄 return { moves: moves, children: children } } /** * 將 list轉變成 key-item keyIndex 對象的形式進行展現. * @param {Array} list * @param {String|Function} key */ function getKeyIndexAndFree (list, key) { let keyIndex = {} let free = [] for (let i = 0, len = list.length; i < len; i++) { let item = list[i] let itemKey = getItemKey(item, key) if (itemKey) { keyIndex[itemKey] = i } else { free.push(item) } } // 返回 key-item keyIndex return { keyIndex: keyIndex, free: free } } function getItemKey (item, key) { if (!item || !key) return void 0 return typeof key === 'string' ? item[key] : key(item) } module.exports = diff // 實現 patch,解析 patch 對象 function patch (rootNode, patches) { let walker = { index: 0 } walk(rootNode, walker, patches) } function walk (node, walker, patches) { let currentPatches = patches[walker.index] // 從patches取出當前節點的差別 let len = node.childNodes ? node.childNodes.length : 0 for (let i = 0; i < len; i++) { // 深度遍歷子節點 let child = node.childNodes[i] walker.index++ walk(child, walker, patches) } if (currentPatches) { dealPatches(node, currentPatches) // 對當前節點進行DOM操做 } } function dealPatches (node, currentPatches) { currentPatches.forEach(currentPatch => { switch (currentPatch.type) { case REPLACE: let newNode = (typeof currentPatch.node === 'string') ? document.createTextNode(currentPatch.node) : currentPatch.node.render() node.parentNode.replaceChild(newNode, node) break case REORDER: reorderChildren(node, currentPatch.moves) break case ATTRS: setProps(node, currentPatch.props) break case TEXT: if (node.textContent) { node.textContent = currentPatch.content } else { // for ie node.nodeValue = currentPatch.content } break default: throw new Error('Unknown patch type ' + currentPatch.type) } }) } function setAttrs (node, props) { for (let key in props) { if (props[key] === void 0) { node.removeAttribute(key) } else { let value = props[key] _.setAttr(node, key, value) } } } function reorderChildren (node, moves) { let staticNodeList = _.toArray(node.childNodes) let maps = {} // 存儲含有key特殊字段的節點 staticNodeList.forEach(node => { // 若是當前節點是ElementNode,經過maps將含有key字段的節點進行存儲 if (_.isElementNode(node)) { let key = node.getAttribute('key') if (key) { maps[key] = node } } }) moves.forEach(move => { let index = move.index if (move.type === 0) { // remove item if (staticNodeList[index] === node.childNodes[index]) { // maybe have been removed for inserting node.removeChild(node.childNodes[index]) } staticNodeList.splice(index, 1) } else if (move.type === 1) { // insert item let insertNode = maps[move.item.key] ? maps[move.item.key] // reuse old item : (typeof move.item === 'object') ? move.item.render() : document.createTextNode(move.item) staticNodeList.splice(index, 0, insertNode) node.insertBefore(insertNode, node.childNodes[index] || null) } }) }
(function(window,undefined){ let njQuery=function(){ return new njQuery.prototype.init(); } njQuery.prototype={ constructor:njQuery } njQuery.prototype.init.prototype=njQuery.prototype; window.njQuery=window.$=njQuery; })(window)
function swap(A,i,j){ const t=A[i]; A[i]=A[j]; A[j]=t; } function buble_sort(A){ // |---未排序---|---已排序的最大值---| // 初始 |------未排序------|i| for(let i=A.length;i>0;i--){ for(let j=1;j<i;j++){ if(A[j]<A[j-1]){ swap(A,j,j-1) } } // 循環不變式成立 } return A }
// i指向最後一個小於支點的數字,j指向未確認的下一個數字 初始值 i=-1,j=0 function swap(A,i,j){ [A[i],A[j]]=[A[j],A[i]]; } function divide(A,p,r){ const x=A[r-1]; let i=p-1; for(let j=p;j<r-1;j++){ if(A[j]<x){ i++; swap(A,i,j); } } swap(A,i+1,r-1); return i+1; } function quick_sort(A,p=0,r){ r = typeof r !== 'undefined' ? r : A.length; if(p<r-1){ const q=divide(A,p,r); quick_sort(A,p,q); quick_sort(A,q+1,r) } }
function insert_sort(A){ for( let j=1; j<A.length; j++){ const key=A[j]; let i=j-1; while(i>=0 && A[i]>key){ A[i+1]=A[i]; i--; } A[i+1]=key } }
const SENTINEL=Number.MAX_SAFE_INTEGER; function divide(p,r){ return Math.floor((p+r)/2) } function conquer(A,p,q,r){ const A1=A.slice(p,q); const A2=A.slice(q,r); A1.push(SENTINEL); A2.push(SENTINEL); for(let k=p,i=0,j=0;k<r;k++){ A[k]=A1[i]<A2[i]?A1[i++]:A2[j++] } } function merge_sort(A,p=0,r){ r=r || A.length; if(r-p===1){return} if(r-p===2){ if(A[p]>A[r-1]){ [A[p],A[r-1]]=[A[r-1],A[p]] } return } const q=divide(p,r); console.log('divide:'+q); merge_sort(A,p,q) merge_sort(A,q,r) conquer(A,p,q,r) }
function bucket_sort(A,max){ const a=max; const B=[...Array(a+1)].map(x=>[]) const indexFunc=(value)=>{ const key=Math.floor(value/a); if(key>a){ return a } return key } A.forEach(value=>{ const idx=Math.floor(indexFunc(value)) if(!B[idx]){ throw new Error('桶腳標沒有命中 index='+idx) } B[idx].push(value) }) return [].concat(...B.map(bucket=>{ return bucket.sort((x,y)=>x-y) })) }
function bsearch(A,x){ let l=0, r=A.length-1, guess; while(l<=r){ guess=Math.floor((l+r)/2); if(A[guess]===x){ return guess; }else if(A[guess]>x){ r=guess-1; }else{ l=guess+1 } } return -1; }
BinarySearchTree
import BinarySearchTreeNode from './BinarySearchTreeNode'; export default class BinarySearchTree { /** * @param {function} [nodeValueCompareFunction] */ constructor(nodeValueCompareFunction) { this.root = new BinarySearchTreeNode(null, nodeValueCompareFunction); // Steal node comparator from the root. this.nodeComparator = this.root.nodeComparator; } /** * @param {*} value * @return {BinarySearchTreeNode} */ insert(value) { return this.root.insert(value); } /** * @param {*} value * @return {boolean} */ contains(value) { return this.root.contains(value); } /** * @param {*} value * @return {boolean} */ remove(value) { return this.root.remove(value); } /** * @return {string} */ toString() { return this.root.toString(); } }
RedBlackTree
import BinarySearchTree from '../binary-search-tree/BinarySearchTree'; // Possible colors of red-black tree nodes. const RED_BLACK_TREE_COLORS = { red: 'red', black: 'black', }; // Color property name in meta information of the nodes. const COLOR_PROP_NAME = 'color'; export default class RedBlackTree extends BinarySearchTree { /** * @param {*} value * @return {BinarySearchTreeNode} */ insert(value) { const insertedNode = super.insert(value); // if (!this.root.left && !this.root.right) { if (this.nodeComparator.equal(insertedNode, this.root)) { // Make root to always be black. this.makeNodeBlack(insertedNode); } else { // Make all newly inserted nodes to be red. this.makeNodeRed(insertedNode); } // Check all conditions and balance the node. this.balance(insertedNode); return insertedNode; } /** * @param {*} value * @return {boolean} */ remove(value) { throw new Error(`Can't remove ${value}. Remove method is not implemented yet`); } /** * @param {BinarySearchTreeNode} node */ balance(node) { // If it is a root node then nothing to balance here. if (this.nodeComparator.equal(node, this.root)) { return; } // If the parent is black then done. Nothing to balance here. if (this.isNodeBlack(node.parent)) { return; } const grandParent = node.parent.parent; if (node.uncle && this.isNodeRed(node.uncle)) { // If node has red uncle then we need to do RECOLORING. // Recolor parent and uncle to black. this.makeNodeBlack(node.uncle); this.makeNodeBlack(node.parent); if (!this.nodeComparator.equal(grandParent, this.root)) { // Recolor grand-parent to red if it is not root. this.makeNodeRed(grandParent); } else { // If grand-parent is black root don't do anything. // Since root already has two black sibling that we've just recolored. return; } // Now do further checking for recolored grand-parent. this.balance(grandParent); } else if (!node.uncle || this.isNodeBlack(node.uncle)) { // If node uncle is black or absent then we need to do ROTATIONS. if (grandParent) { // Grand parent that we will receive after rotations. let newGrandParent; if (this.nodeComparator.equal(grandParent.left, node.parent)) { // Left case. if (this.nodeComparator.equal(node.parent.left, node)) { // Left-left case. newGrandParent = this.leftLeftRotation(grandParent); } else { // Left-right case. newGrandParent = this.leftRightRotation(grandParent); } } else { // Right case. if (this.nodeComparator.equal(node.parent.right, node)) { // Right-right case. newGrandParent = this.rightRightRotation(grandParent); } else { // Right-left case. newGrandParent = this.rightLeftRotation(grandParent); } } // Set newGrandParent as a root if it doesn't have parent. if (newGrandParent && newGrandParent.parent === null) { this.root = newGrandParent; // Recolor root into black. this.makeNodeBlack(this.root); } // Check if new grand parent don't violate red-black-tree rules. this.balance(newGrandParent); } } } /** * Left Left Case (p is left child of g and x is left child of p) * @param {BinarySearchTreeNode|BinaryTreeNode} grandParentNode * @return {BinarySearchTreeNode} */ leftLeftRotation(grandParentNode) { // Memorize the parent of grand-parent node. const grandGrandParent = grandParentNode.parent; // Check what type of sibling is our grandParentNode is (left or right). let grandParentNodeIsLeft; if (grandGrandParent) { grandParentNodeIsLeft = this.nodeComparator.equal(grandGrandParent.left, grandParentNode); } // Memorize grandParentNode's left node. const parentNode = grandParentNode.left; // Memorize parent's right node since we're going to transfer it to // grand parent's left subtree. const parentRightNode = parentNode.right; // Make grandParentNode to be right child of parentNode. parentNode.setRight(grandParentNode); // Move child's right subtree to grandParentNode's left subtree. grandParentNode.setLeft(parentRightNode); // Put parentNode node in place of grandParentNode. if (grandGrandParent) { if (grandParentNodeIsLeft) { grandGrandParent.setLeft(parentNode); } else { grandGrandParent.setRight(parentNode); } } else { // Make parent node a root parentNode.parent = null; } // Swap colors of granParent and parent nodes. this.swapNodeColors(parentNode, grandParentNode); // Return new root node. return parentNode; } /** * Left Right Case (p is left child of g and x is right child of p) * @param {BinarySearchTreeNode|BinaryTreeNode} grandParentNode * @return {BinarySearchTreeNode} */ leftRightRotation(grandParentNode) { // Memorize left and left-right nodes. const parentNode = grandParentNode.left; const childNode = parentNode.right; // We need to memorize child left node to prevent losing // left child subtree. Later it will be re-assigned to // parent's right sub-tree. const childLeftNode = childNode.left; // Make parentNode to be a left child of childNode node. childNode.setLeft(parentNode); // Move child's left subtree to parent's right subtree. parentNode.setRight(childLeftNode); // Put left-right node in place of left node. grandParentNode.setLeft(childNode); // Now we're ready to do left-left rotation. return this.leftLeftRotation(grandParentNode); } /** * Right Right Case (p is right child of g and x is right child of p) * @param {BinarySearchTreeNode|BinaryTreeNode} grandParentNode * @return {BinarySearchTreeNode} */ rightRightRotation(grandParentNode) { // Memorize the parent of grand-parent node. const grandGrandParent = grandParentNode.parent; // Check what type of sibling is our grandParentNode is (left or right). let grandParentNodeIsLeft; if (grandGrandParent) { grandParentNodeIsLeft = this.nodeComparator.equal(grandGrandParent.left, grandParentNode); } // Memorize grandParentNode's right node. const parentNode = grandParentNode.right; // Memorize parent's left node since we're going to transfer it to // grand parent's right subtree. const parentLeftNode = parentNode.left; // Make grandParentNode to be left child of parentNode. parentNode.setLeft(grandParentNode); // Transfer all left nodes from parent to right sub-tree of grandparent. grandParentNode.setRight(parentLeftNode); // Put parentNode node in place of grandParentNode. if (grandGrandParent) { if (grandParentNodeIsLeft) { grandGrandParent.setLeft(parentNode); } else { grandGrandParent.setRight(parentNode); } } else { // Make parent node a root. parentNode.parent = null; } // Swap colors of granParent and parent nodes. this.swapNodeColors(parentNode, grandParentNode); // Return new root node. return parentNode; } /** * Right Left Case (p is right child of g and x is left child of p) * @param {BinarySearchTreeNode|BinaryTreeNode} grandParentNode * @return {BinarySearchTreeNode} */ rightLeftRotation(grandParentNode) { // Memorize right and right-left nodes. const parentNode = grandParentNode.right; const childNode = parentNode.left; // We need to memorize child right node to prevent losing // right child subtree. Later it will be re-assigned to // parent's left sub-tree. const childRightNode = childNode.right; // Make parentNode to be a right child of childNode. childNode.setRight(parentNode); // Move child's right subtree to parent's left subtree. parentNode.setLeft(childRightNode); // Put childNode node in place of parentNode. grandParentNode.setRight(childNode); // Now we're ready to do right-right rotation. return this.rightRightRotation(grandParentNode); } /** * @param {BinarySearchTreeNode|BinaryTreeNode} node * @return {BinarySearchTreeNode} */ makeNodeRed(node) { node.meta.set(COLOR_PROP_NAME, RED_BLACK_TREE_COLORS.red); return node; } /** * @param {BinarySearchTreeNode|BinaryTreeNode} node * @return {BinarySearchTreeNode} */ makeNodeBlack(node) { node.meta.set(COLOR_PROP_NAME, RED_BLACK_TREE_COLORS.black); return node; } /** * @param {BinarySearchTreeNode|BinaryTreeNode} node * @return {boolean} */ isNodeRed(node) { return node.meta.get(COLOR_PROP_NAME) === RED_BLACK_TREE_COLORS.red; } /** * @param {BinarySearchTreeNode|BinaryTreeNode} node * @return {boolean} */ isNodeBlack(node) { return node.meta.get(COLOR_PROP_NAME) === RED_BLACK_TREE_COLORS.black; } /** * @param {BinarySearchTreeNode|BinaryTreeNode} node * @return {boolean} */ isNodeColored(node) { return this.isNodeRed(node) || this.isNodeBlack(node); } /** * @param {BinarySearchTreeNode|BinaryTreeNode} firstNode * @param {BinarySearchTreeNode|BinaryTreeNode} secondNode */ swapNodeColors(firstNode, secondNode) { const firstColor = firstNode.meta.get(COLOR_PROP_NAME); const secondColor = secondNode.meta.get(COLOR_PROP_NAME); firstNode.meta.set(COLOR_PROP_NAME, secondColor); secondNode.meta.set(COLOR_PROP_NAME, firstColor); } }
import isPowerOfTwo from '../../../algorithms/math/is-power-of-two/isPowerOfTwo'; export default class SegmentTree { /** * @param {number[]} inputArray * @param {function} operation - binary function (i.e. sum, min) * @param {number} operationFallback - operation fallback value (i.e. 0 for sum, Infinity for min) */ constructor(inputArray, operation, operationFallback) { this.inputArray = inputArray; this.operation = operation; this.operationFallback = operationFallback; // Init array representation of segment tree. this.segmentTree = this.initSegmentTree(this.inputArray); this.buildSegmentTree(); } /** * @param {number[]} inputArray * @return {number[]} */ initSegmentTree(inputArray) { let segmentTreeArrayLength; const inputArrayLength = inputArray.length; if (isPowerOfTwo(inputArrayLength)) { // If original array length is a power of two. segmentTreeArrayLength = (2 * inputArrayLength) - 1; } else { // If original array length is not a power of two then we need to find // next number that is a power of two and use it to calculate // tree array size. This is happens because we need to fill empty children // in perfect binary tree with nulls.And those nulls need extra space. const currentPower = Math.floor(Math.log2(inputArrayLength)); const nextPower = currentPower + 1; const nextPowerOfTwoNumber = 2 ** nextPower; segmentTreeArrayLength = (2 * nextPowerOfTwoNumber) - 1; } return new Array(segmentTreeArrayLength).fill(null); } /** * Build segment tree. */ buildSegmentTree() { const leftIndex = 0; const rightIndex = this.inputArray.length - 1; const position = 0; this.buildTreeRecursively(leftIndex, rightIndex, position); } /** * Build segment tree recursively. * * @param {number} leftInputIndex * @param {number} rightInputIndex * @param {number} position */ buildTreeRecursively(leftInputIndex, rightInputIndex, position) { // If low input index and high input index are equal that would mean // the we have finished splitting and we are already came to the leaf // of the segment tree. We need to copy this leaf value from input // array to segment tree. if (leftInputIndex === rightInputIndex) { this.segmentTree[position] = this.inputArray[leftInputIndex]; return; } // Split input array on two halves and process them recursively. const middleIndex = Math.floor((leftInputIndex + rightInputIndex) / 2); // Process left half of the input array. this.buildTreeRecursively(leftInputIndex, middleIndex, this.getLeftChildIndex(position)); // Process right half of the input array. this.buildTreeRecursively(middleIndex + 1, rightInputIndex, this.getRightChildIndex(position)); // Once every tree leaf is not empty we're able to build tree bottom up using // provided operation function. this.segmentTree[position] = this.operation( this.segmentTree[this.getLeftChildIndex(position)], this.segmentTree[this.getRightChildIndex(position)], ); } /** * Do range query on segment tree in context of this.operation function. * * @param {number} queryLeftIndex * @param {number} queryRightIndex * @return {number} */ rangeQuery(queryLeftIndex, queryRightIndex) { const leftIndex = 0; const rightIndex = this.inputArray.length - 1; const position = 0; return this.rangeQueryRecursive( queryLeftIndex, queryRightIndex, leftIndex, rightIndex, position, ); } /** * Do range query on segment tree recursively in context of this.operation function. * * @param {number} queryLeftIndex - left index of the query * @param {number} queryRightIndex - right index of the query * @param {number} leftIndex - left index of input array segment * @param {number} rightIndex - right index of input array segment * @param {number} position - root position in binary tree * @return {number} */ rangeQueryRecursive(queryLeftIndex, queryRightIndex, leftIndex, rightIndex, position) { if (queryLeftIndex <= leftIndex && queryRightIndex >= rightIndex) { // Total overlap. return this.segmentTree[position]; } if (queryLeftIndex > rightIndex || queryRightIndex < leftIndex) { // No overlap. return this.operationFallback; } // Partial overlap. const middleIndex = Math.floor((leftIndex + rightIndex) / 2); const leftOperationResult = this.rangeQueryRecursive( queryLeftIndex, queryRightIndex, leftIndex, middleIndex, this.getLeftChildIndex(position), ); const rightOperationResult = this.rangeQueryRecursive( queryLeftIndex, queryRightIndex, middleIndex + 1, rightIndex, this.getRightChildIndex(position), ); return this.operation(leftOperationResult, rightOperationResult); } /** * Left child index. * @param {number} parentIndex * @return {number} */ getLeftChildIndex(parentIndex) { return (2 * parentIndex) + 1; } /** * Right child index. * @param {number} parentIndex * @return {number} */ getRightChildIndex(parentIndex) { return (2 * parentIndex) + 2; } }
TrieNode
import HashTable from '../hash-table/HashTable'; export default class TrieNode { /** * @param {string} character * @param {boolean} isCompleteWord */ constructor(character, isCompleteWord = false) { this.character = character; this.isCompleteWord = isCompleteWord; this.children = new HashTable(); } /** * @param {string} character * @return {TrieNode} */ getChild(character) { return this.children.get(character); } /** * @param {string} character * @param {boolean} isCompleteWord * @return {TrieNode} */ addChild(character, isCompleteWord = false) { if (!this.children.has(character)) { this.children.set(character, new TrieNode(character, isCompleteWord)); } const childNode = this.children.get(character); // In cases similar to adding "car" after "carpet" we need to mark "r" character as complete. childNode.isCompleteWord = childNode.isCompleteWord || isCompleteWord; return childNode; } /** * @param {string} character * @return {TrieNode} */ removeChild(character) { const childNode = this.getChild(character); // Delete childNode only if: // - childNode has NO children, // - childNode.isCompleteWord === false. if ( childNode && !childNode.isCompleteWord && !childNode.hasChildren() ) { this.children.delete(character); } return this; } /** * @param {string} character * @return {boolean} */ hasChild(character) { return this.children.has(character); } /** * Check whether current TrieNode has children or not. * @return {boolean} */ hasChildren() { return this.children.getKeys().length !== 0; } /** * @return {string[]} */ suggestChildren() { return [...this.children.getKeys()]; } /** * @return {string} */ toString() { let childrenAsString = this.suggestChildren().toString(); childrenAsString = childrenAsString ? `:${childrenAsString}` : ''; const isCompleteString = this.isCompleteWord ? '*' : ''; return `${this.character}${isCompleteString}${childrenAsString}`; } }
Tri
import TrieNode from './TrieNode'; // Character that we will use for trie tree root. const HEAD_CHARACTER = '*'; export default class Trie { constructor() { this.head = new TrieNode(HEAD_CHARACTER); } /** * @param {string} word * @return {Trie} */ addWord(word) { const characters = Array.from(word); let currentNode = this.head; for (let charIndex = 0; charIndex < characters.length; charIndex += 1) { const isComplete = charIndex === characters.length - 1; currentNode = currentNode.addChild(characters[charIndex], isComplete); } return this; } /** * @param {string} word * @return {Trie} */ deleteWord(word) { const depthFirstDelete = (currentNode, charIndex = 0) => { if (charIndex >= word.length) { // Return if we're trying to delete the character that is out of word's scope. return; } const character = word[charIndex]; const nextNode = currentNode.getChild(character); if (nextNode == null) { // Return if we're trying to delete a word that has not been added to the Trie. return; } // Go deeper. depthFirstDelete(nextNode, charIndex + 1); // Since we're going to delete a word let's un-mark its last character isCompleteWord flag. if (charIndex === (word.length - 1)) { nextNode.isCompleteWord = false; } // childNode is deleted only if: // - childNode has NO children // - childNode.isCompleteWord === false currentNode.removeChild(character); }; // Start depth-first deletion from the head node. depthFirstDelete(this.head); return this; } /** * @param {string} word * @return {string[]} */ suggestNextCharacters(word) { const lastCharacter = this.getLastCharacterNode(word); if (!lastCharacter) { return null; } return lastCharacter.suggestChildren(); } /** * Check if complete word exists in Trie. * * @param {string} word * @return {boolean} */ doesWordExist(word) { const lastCharacter = this.getLastCharacterNode(word); return !!lastCharacter && lastCharacter.isCompleteWord; } /** * @param {string} word * @return {TrieNode} */ getLastCharacterNode(word) { const characters = Array.from(word); let currentNode = this.head; for (let charIndex = 0; charIndex < characters.length; charIndex += 1) { if (!currentNode.hasChild(characters[charIndex])) { return null; } currentNode = currentNode.getChild(characters[charIndex]); } return currentNode; } }
function match(n,c){ return ( c=='[' && n==']' ) || ( c=='(' && n==')' ) } function is_balance(str){ const [first,...others]=str; const stack=[first]; while(others.length>0){ const c=stack[stack.length-1]; const n=others.shift(); if(!match(n,c)){ stack.push(n) }else{ stack.pop() } } return stack.length === 0; }
堆棧實現深度優先遍歷
function depth_first_search(node){ let stack=[node]; while(stack.length>0){ const item=stack.pop(); for(let i=item.length-1;i>0;i--){ stack.push(item.children[i]) } } }
隊列實現廣度優先搜索
function *breath_first_search(node){ let queue=[node]; while(queue.length>0){ const item=queue.pop(); yield item.tagName; for(let i=item.length-1;i>0;i--){ queue.unshift(item.children[i]) } } }
// 判斷棋盤上兩個皇后是否互相攻擊 function compatible(p,q,n){ const [x1,y1]=[~~(p/n),p%n]; const [x2,y2]=[~~(q/n),q%n]; return ( x1 !== x2 && y1 !== y2 && Math.abs(x1-x2) !== Math.abs(y1-y2) ) } function queen(n,decisions=[]){ if(decisions.length===n){ return [decisions] } let r=[]; const start=decisions[decisions.length-1] || -1; for(let i=start+1;i<n*n;i++){ if(decisions.indexOf(i)===-1){ if(decisions.every(j=>compatible(j,i,n))){ r=r.concat(queen(n,decisions.concat(i))) } } } return r; }
class List{ ... reverse(p=this.head){ if(p.next){ this.reverse(p.next); p.next.next=p; p.next=null }else{ this.head=p } } }
export default function longestCommonSubsequence(set1, set2) { // Init LCS matrix. const lcsMatrix = Array(set2.length + 1).fill(null).map(() => Array(set1.length + 1).fill(null)); // Fill first row with zeros. for (let columnIndex = 0; columnIndex <= set1.length; columnIndex += 1) { lcsMatrix[0][columnIndex] = 0; } // Fill first column with zeros. for (let rowIndex = 0; rowIndex <= set2.length; rowIndex += 1) { lcsMatrix[rowIndex][0] = 0; } // Fill rest of the column that correspond to each of two strings. for (let rowIndex = 1; rowIndex <= set2.length; rowIndex += 1) { for (let columnIndex = 1; columnIndex <= set1.length; columnIndex += 1) { if (set1[columnIndex - 1] === set2[rowIndex - 1]) { lcsMatrix[rowIndex][columnIndex] = lcsMatrix[rowIndex - 1][columnIndex - 1] + 1; } else { lcsMatrix[rowIndex][columnIndex] = Math.max( lcsMatrix[rowIndex - 1][columnIndex], lcsMatrix[rowIndex][columnIndex - 1], ); } } } // Calculate LCS based on LCS matrix. if (!lcsMatrix[set2.length][set1.length]) { // If the length of largest common string is zero then return empty string. return ['']; } const longestSequence = []; let columnIndex = set1.length; let rowIndex = set2.length; while (columnIndex > 0 || rowIndex > 0) { if (set1[columnIndex - 1] === set2[rowIndex - 1]) { // Move by diagonal left-top. longestSequence.unshift(set1[columnIndex - 1]); columnIndex -= 1; rowIndex -= 1; } else if (lcsMatrix[rowIndex][columnIndex] === lcsMatrix[rowIndex][columnIndex - 1]) { // Move left. columnIndex -= 1; } else { // Move up. rowIndex -= 1; } } return longestSequence; }
function reverseBTree(node){ if(!node){ return } const tmp=node.left; node.left=node.right; node.right=tmp; reverseBTree(node.left); reverseBTree(node.right) }
/** * 1 * 5 9 * 4 2 7 3 * 8 */ // 求一個二叉樹從左側看的輪廓,如圖,返回[1,5,4,8]?若是求每行最大值,返回[1,9,7,8]該如何作? function leftoutlineTree(node,d=0,outline=[]){ if(!node){ return } if(!outline[d]){ outline[d]=node.value } leftoutlineTree(node.left,d+1,outline); leftoutlineTree(node.right,d+1,outline); return outline; } function maxOfLine(node,d=0,outline=[]){ if(!node){ return } outline[d]=Math.max(outline[d] || -1,node.value); maxOfLine(node.left,d+1,outline); maxOfLine(node.right,d+1,outline); return outline; }
class Queue{ constructor({ this.s1=[]; this.s2=[]; } enqueue(item){ this.s1.push(item) } dequeue(){ while(this.s1.length>0){ this.s2.push(this.s1.pop()); } if(this.s2.length>0){ return this.s2.pop(); } } }
<div class="container" id="container"> <div id="btn-prev" class="btn-ctrl"><</div> <div id="btn-next" class="btn-ctrl">></div> <ul id="inner-list"> <li><img src="images/head1.jpeg" alt=""/></li> <li><img src="images/head2.jpeg" alt=""/></li> <li><img src="images/head3.jpeg" alt=""/></li> </ul> <ul id="dot-list"> </ul> </div>
window.onload = function(){ var eleInners = document.getElementById('inner-list'), eleDots = document.getElementById('dot-list'), liImgs = eleInners.getElementsByTagName('li'), liDots = eleDots.children, elePrev = document.getElementById('btn-prev'), eleNext = document.getElementById('btn-next'), LI_WIDTH = liImgs[0].offsetWidth, TIME_DURATION = 3000, interval = null, index = 0, circle = 0; eleInners.appendChild(liImgs[0].cloneNode(true)); for(var i= 0,len = liImgs.length -1;i<len;i++){ var li = document.createElement('li'); li.innerHTML = i+1; eleDots.appendChild(li) }; liDots[0].className = 'cur'; function animate(obj,targetPlace){ clearInterval(obj.timer); obj.timer = setInterval(function(){ var speed = obj.offsetLeft > targetPlace ? -15:15; var result = targetPlace - obj.offsetLeft; if(Math.abs(result) > Math.abs(speed)){ obj.style.left = obj.offsetLeft + speed +'px' }else{ obj.style.left = targetPlace+'px'; clearInterval(obj.timer); } },10) } interval = setInterval(autoplay,3000) function autoplay(){ index++; if(index > liImgs.length -1){ eleInners.style.left = 0; index = 1; } animate(eleInners, -index * LI_WIDTH); circle++; if(circle >= liImgs.length -1){ circle = 0; } for(var i= 0,len = liDots.length;i<len;i++){ liDots[i].className =''; } liDots[circle].className = 'cur'; } function moveright(){ index--; if(index <0){ eleInners.style.left = -(liImgs.length -2)* LI_WIDTH + 'px'; index = liImgs.length -2; } animate(eleInners, -index * LI_WIDTH); circle --; if(circle < 0){ circle = liImgs.length - 2;//circle回到最後一個點 } for(var i= 0,len = liDots.length;i<len;i++){ liDots[i].className =''; } liDots[circle].className = 'cur' } eleInners.addEventListener('mouseenter',function(event){ clearInterval(interval) }); eleInners.addEventListener('mouseleave',function(event){ interval = setInterval(autoplay,3000) }); eleDots.addEventListener('click',function(event){ clearInterval(interval); var target = event.target; var currentTarget = event.currentTarget; index = target.innerHTML - 0 - 1; circle = index ; for(var i= 0,len = liDots.length;i<len;i++){ liDots[i].className =''; } liDots[circle].className = 'cur'; animate(eleInners, - index * LI_WIDTH); }) elePrev.addEventListener('click',function(event){ clearInterval(interval) moveright(); interval = setInterval(autoplay,3000) }) eleNext.addEventListener('click',function(event){ clearInterval(interval); autoplay(); interval = setInterval(autoplay,3000); }) }
<div class="myDiv"></div>
.myDiv{ width: 600px; height: 400px; margin: 20px auto; background-size: over; background-position: center; animation-name:loop; animation-duration: 20s; animation-iteration-count: infinite; } @keyframes loop{ 0% {background: url('圖片1.jpg') no-repeat;} 25% {background: url('圖片2.jpg') no-repeat;} 50% {background: url('圖片3.jpg') no-repeat;} 75% {background: url('圖片4.jpg') no-repeat;} 100% {background: url('圖片5.jpg') no-repeat;} }
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> body { margin: 0; } .waterfall-container { /*分幾列*/ column-count: 2; width: 100%; /* 列間距 */ column-gap: 10px; } .waterfall-item { break-inside: avoid; width: 100%; height: 100px; margin-bottom: 10px; background: #ddd; column-gap: 0; text-align: center; color: #fff; font-size: 40px; } </style> </head> <body> <div class="waterfall-container"> <div class="waterfall-item" style="height: 100px">1</div> <div class="waterfall-item" style="height: 300px">2</div> <div class="waterfall-item" style="height: 400px">3</div> <div class="waterfall-item" style="height: 100px">4</div> <div class="waterfall-item" style="height: 300px">5</div> <div class="waterfall-item" style="height: 600px">6</div> <div class="waterfall-item" style="height: 400px">7</div> <div class="waterfall-item" style="height: 300px">8</div> <div class="waterfall-item" style="height: 700px">9</div> <div class="waterfall-item" style="height: 100px">10</div> </div> </body> </html>
Flex 佈局
<style> .container{ display:flex; justify-content: center; height: 200px; background: #eee; } .left { width: 200px; background-color: red; height: 100%; } .main { background-color: yellow; flex: 1; } .right { width: 200px; background-color: green; } </style> <div class="container"> <div class="left">1</div> <div class="main">2</div> <div class="right">3</div> </div>
絕對定位佈局
<style> .container { position: relative; background:#eee; height:200px; } .main { height: 200px; margin: 0 120px; background-color: yellow; } .left { position: absolute; width: 100px; height: 200px; left: 0; top: 0; background-color: red; } .right { position: absolute; width: 100px; height: 200px; background-color: green; right: 0; top: 0; } </style> <div class="container"> <div class="left">1</div> <div class="main">2</div> <div class="right">3</div> </div>
雙飛翼佈局
<style> .content { float: left; width: 100%; } .main { height: 200px; margin-left: 110px; margin-right: 220px; background-color: yellow; } .left { float: left; height: 200px; width: 100px; margin-left: -100%; background-color: red; } .right { width: 200px; height: 200px; float: right; margin-left: -200px; background-color: green; } </style> <div class="content"> <div class="main"></div> </div> <div class="left"></div> <div class="right"></div>
聖盃佈局
<style> .container { margin-left: 120px; margin-right: 220px; } .main { float: left; width: 100%; height: 300px; background-color: yellow; } .left { float: left; width: 100px; height: 300px; margin-left: -100%; position: relative; left: -120px; background-color: blue; } .right { float: left; width: 200px; height: 300px; margin-left: -200px; position: relative; right: -220px; background-color: green; } </style> <div class="container"> <div class="main"></div> <div class="left"></div> <div class="right"></div> </div>
<div class="wrap"> <div class="div1"></div> <div class="div2"></div> </div> .wrap { display: flex; justify-content: space-between; } .div1 { min-width: 200px; } .div2 { width: 100%; background: #e6e6e6; } html, body, div { height: 100%; margin: 0; }
<canvas id="canvas" width="300px" height="300px"></canvas>
let ctx=document.getElementById('canvas').getContext('2d'); ctx.beginPath(); ctx.moveTo(0,150); ctx.lineTo(150,0); ctx.lineTo(300,150); ctx.closePath(); ctx.strokeStyle='#666'; ctx.lineWidth=3; ctx.stroke();
單行
overflow: hidden; text-overflow:ellipsis; white-space: nowrap;
多行
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; // 最多顯示幾行 overflow: hidden;
.info-tab { position: relative; } .info-tab::after { content: ''; border: 4px solid transparent; border-top-color: #2c8ac2; position: absolute; top: 0; }
div { width: 200px; height: 200px; } img { object-fit: cover; width: 100%; height: 100%; }
<style> .line { position: relative; } .line:after { content: ""; position: absolute; left: 0; top: 0; width: 100%; height: 1px; background-color: #000000; -webkit-transform: scaleY(.5); transform: scaleY(.5); } </style> <div class="line"></div>
遞歸
function fib(n) { return fib(n) = n > 2 ? fib(n - 1) + fib(n - 2) : 1 }
尾遞歸
function fib(n,a=1,b=1){ if(n<=1) return b; return fib(n-1,b,a+b); }
非遞歸 動態規劃
function fib(n){ let a=1, b=1; for(let i=2;i<n;i++){ const t=b; b=a+b; a=t } return b }
非遞歸 生成器
function *fib(){ let a=1,b=1; yield a; yield b; while(true){ const t=b; b=a+b; a=t; yield b } }
遞歸 reduce流
function fib(n){ return Array(n).fill().reduce(([a,b],_)=>{ return [b,a+b] },[0,1])[0] }
非遞歸 堆棧
function fib(n){ let stack=[n] while(stack.length){ const item=stack.pop(); if(item===1 || item===2){ stack.push(1) }else{ stack.push(item-1); stack.push(item-2); } } }
function is_prime(n){ if(n<=1){return false} const N=Math.floor(Math.sqrt(n)); let is_prime=true for(let i=2;i<=N;i++){ if(n%i===0){ is_prime=false; break; } } return is_prime; }
function *sieve_primes(n){ let numbers=Array.from({length:n-2},(_,i)=>i+2); let p=null; while((p=numbers.shift())){ yield p; numbers=numbers.filter(t=>t%p!==0) } }
function insert(arr, item, index) { return arr.slice(0,index).concat(item,arr.slice(index)); }
function insert(arr, item, index) { var newArr=arr.concat(); newArr.splice(index,0,item); return newArr; }
function insert(arr, item, index) { var newArr=arr.slice(0); newArr.splice(index,0,item); return newArr; }
function insert(arr, item, index) { var newArr=[]; [].push.apply(newArr, arr); newArr.splice(index,0,item); return newArr; }
function count(start, end) { console.log(start) var timer = setInterval( function(){ if(start<end) console.log(start+=1); },100) return {cancel:function(){clearInterval(timer)}} }
function compare(propertyName, index) { return function(a, b) { let value1 = a[propertyName]; let value2 = b[propertyName]; if (vm.reverse[index]) { return value2 - value1; } else { return value1 - value2; } }; }
let num=0; let char=''; let str = str.split('').sort().join(''); str.replace(/(\w)\1+/g,($0,$1) => { if(num < $0.length){ num = $0.length; char = $1; } }); console.log(`字符最多的是${char},出現了${num}次`);
function shuffle_simple(arr){ return arr.sort(()=>Math.random()- .5) }
或
function fisher_yates_shuffle(arr){ for(let i=0;i<arr.length-1;i++){ const j=i+Math.floor(Math.random()*(arr.length-1)); [arr[i],[arr[j]]]=[arr[j],arr[i]] } return arr }
或
function shuffle(arr){ const m=[]; const N=arr.length*arr.length*arr.length; for(let i=0;i<arr.length-1;i++){ m[i]=Math.floor(Math.random(1,N)) } return arr.sort((i,j)=>m[i]-m[j]) }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> #div_main { margin: 0 auto; width: 300px; height: 400px; border: 1px solid black; margin-top: 50px; } #div_txt { position: relative; width: 200px; margin: 0 auto; margin-top: 40px; } #txt1 { width: 99%; } #div_items { position: relative; width: 100%; height: 200px; border: 1px solid #66afe9; border-top: 0px; overflow: auto; display: none; } .div_item { width: 100%; height: 20px; margin-top: 1px; font-size: 13px; line-height: 20px; } </style> </head> <body> <div id="div_main"> <!--表單的autocomplete="off"屬性設置能夠阻止瀏覽器默認的提示框--> <form autocomplete="off"> <div id="div_txt"> <!--要模糊匹配的文本框--> <input type="text" id="txt1" /> <!--模糊匹配窗口--> <div id="div_items"> <div class="div_item">周杰倫</div> <div class="div_item">周杰</div> <div class="div_item">林俊杰</div> <div class="div_item">林宥嘉</div> <div class="div_item">林妙可</div> <div class="div_item">唐嫣</div> <div class="div_item">唐家三少</div> <div class="div_item">唐朝盛世</div> <div class="div_item">奧迪A4L</div> <div class="div_item">奧迪A6L</div> <div class="div_item">奧迪A8L</div> <div class="div_item">奧迪R8</div> <div class="div_item">寶馬GT</div> </div> </div> </form> </div> <script src="./jquery.min.js"></script> <script type="text/javascript"> //彈出列表框 $("#txt1").click(function () { $("#div_items").css('display', 'block'); return false; }); //隱藏列表框 $("body").click(function () { $("#div_items").css('display', 'none'); }); //移入移出效果 $(".div_item").hover(function () { $(this).css('background-color', '#1C86EE').css('color', 'white'); }, function () { $(this).css('background-color', 'white').css('color', 'black'); }); //文本框輸入 $("#txt1").keyup(function () { $("#div_items").css('display', 'block');//只要輸入就顯示列表框 if ($("#txt1").val().length <= 0) { $(".div_item").css('display', 'block');//若是什麼都沒填,跳出,保持所有顯示狀態 return; } $(".div_item").css('display', 'none');//若是填了,先將全部的選項隱藏 for (var i = 0; i < $(".div_item").length; i++) { //模糊匹配,將全部匹配項顯示 if ($(".div_item").eq(i).text().substr(0, $("#txt1").val().length) == $("#txt1").val()) { $(".div_item").eq(i).css('display', 'block'); } } }); //項點擊 $(".div_item").click(function () { $("#txt1").val($(this).text()); }); </script> </body> </html>
<!DOCTYPE html> <html> <head lang="ch"> <meta charset="UTF-8"> <meta name=」viewport」 content="width=device-width, user-scalable=no, initial-scale=1.0"> <title></title> <style> body, html{ padding: 0; margin: 0; } body, html { height: 100%; overflow: hidden; } #container, .section { height: 100%; } .section { background-color: #000; background-size: cover; background-position: 50% 50%; } #section0 { background-color: #83af9b; } #section1 { background-color: #764d39; } #section2 { background-color: #ff9000; } #section3 { background-color: #380d31; } </style> </head> <body> <div id="container"> <div class="section" id="section0"></div> <div class="section" id="section1"></div> <div class="section" id="section2"></div> <div class="section" id="section3"></div> </div> <script src="http://code.jquery.com/jquery-latest.js"></script> <script> var curIndex = 0; var container = $("#container"); var sumCount = $(".section").length; var $window = $(window); var duration = 500; //時間控制 var aniTime = 0; var scrollFunc = function (e) { //若是動畫還沒執行完,則return if(new Date().getTime() < aniTime + duration){ return; } e = e || window.event; var t = 0; if (e.wheelDelta) {//IE/Opera/Chrome t = e.wheelDelta; if (t > 0 && curIndex > 0) { //上滾動 movePrev(); } else if (t < 0 && curIndex < sumCount - 1) { //下滾動 moveNext(); } } else if (e.detail) {//Firefox t = e.detail; if (t < 0 && curIndex > 0) { //上滾動 movePrev(); } else if (t > 0 && curIndex < sumCount - 1) { //下滾動 moveNext(); } } }; function moveNext(){ //獲取動畫開始時的時間 aniTime = new Date().getTime(); container.css("transform", "translate3D(0, -" + (++curIndex) * $window.height() + "px, 0)"); } function movePrev(){ //獲取動畫開始時的時間 aniTime = new Date().getTime(); container.css("transform", "translate3D(0, -" + (--curIndex) * $window.height() + "px, 0)"); } function init(){ /*註冊事件*/ if (document.addEventListener) { document.addEventListener('DOMMouseScroll', scrollFunc, false); }//W3C window.onmousewheel = document.onmousewheel = scrollFunc;//IE/Opera/Chrome container.css({ "transition": "all 0.5s", "-moz-transition": "all 0.5s", "-webkit-transition": "all 0.5s" }); } init(); </script> </body> </html>
var left_top=$(".left_div>div:last-child").offset().top var right_top=$(".right_div>div:last-child").offset().top if(left_top<=right_top){ $(".left_div").append(img_info) }else{ $(".right_div").append(img_info) }
function get_layout(ele){ const layout={ width:ele.offsetWidth, height:ele.offsetHeight, left:ele.offsetLeft, top:ele.offsetTop } if(ele.offsetParent){ const parentLayout=get_layout(ele.offsetParent); layout.left+=parentLayout.left; layout.top+=parentLayout.top; } return layout; }
function solve(arr,N){ const s=new Set([arr.shift()%N]); while(arr.length>0){ const ak=arr.shift(); const items=[...s]; items.forEach(x=>{ s.add((x+ak)%N); }) s.add(ak) } return s.has(0); }
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <body> <a href="#">第一個連接</a></br> <a href="#">第二個連接</a></br> <a href="#">第三個連接</a></br> <a href="#">第四個連接</a></br> </body>
<script> let aGroup=document.getElementsByTagName('a'); let i=0; for(let a of aGroup){ a.onclick=(function(i){ return function(){ alert(i); } })(++i) } </script>
方式一:
for(let i = 0, len = lis.length; i < len; i++){ lis[i].addEventListener('click', function () { console.log(i); }, false); }
方式二:
for(var i = 0, len = lis.length; i < len; i++) { (function (i) { lis[i].addEventListener ('click', function () { console.log(i); }, false); })(i) }
方式三:
let ul = document.querySelector('ul'); let lis = document.querySelectorAll('ul li'); ul.addEventListener('click', function (e) { let target = e.target; if(target.nodeName.toLowerCase() === 'li') { console.log([].indexOf.call(lis, target)); } }, false);
// 點擊提交按鈕的時候, // 把這個提交這個處理函數給解綁掉, // 請求完成的時候在綁定回來 function clickHandler(){ $(this).unbind('click', clickHandler); $.ajax({ url : 'url', dataType : 'json', type : 'post', success : function (data) { if (data.success) { //提交成功作跳轉處理 } else { //處理失敗,從新綁定點擊事件 $(self).click(clickHandler); } } }); } $('#itlike').click(clickHandler); // 能夠點擊後讓按鈕不可用, // 若是提交失敗能夠再次設置爲可用 // 1.讓按鈕不可用 $("#itlike").attr("disabled","disabled"); $.ajax({ url : 'url', dataType : 'json', type : 'post', success : function (data) { if (data.success) { // 提交成功作跳轉處理 } else { // 處理失敗,從新綁定點擊事件 // 2. 讓按鈕可用 $("#itlike").removeAttr("disabled"); } } });
$(document).ready(function(){ var stopScrolling = function(event) { event.preventDefault(); } document.addEventListener('touchstart', stopScrolling, false); document.addEventListener('touchmove', stopScrolling, false); });
// 給定一個不重複的正整數集合,從中取N個數字,使得它們的和爲M,寫一個函數,求這N個數字。若有多個,只須要返回一個 function sumN(A,n,m,i=0,decisions=[]){ if(m===0){ return decisions } if(i===A.length || n===0 || m<0){ return null } return sumN(A,n-1,m-A[i],i+1,decisions.concat(A[i])) || sumN(A,n,m,i+1,decisions) }
優化
function sumN(A,n,m){ // 最終結果 let r=null; // 決策 const decisions=[]; function inner(i=0,n,m){ // 若是已有結果,終止遞歸 if(r){return} // 若是m=0,找到一個解 if(m===0){ r=decisions.slice(); return } // 沒有找到解的狀況 if(i===A.length || n===0 || m<0){ return } decisions.push(A[i]); inner(i+1,n-1,m-A[i]); decisions.pop(A[i]); inner(i+1,n,m) } inner(0,n,m); return r; }
利用位運算
function sumByBinaryCode(A,code){ const max=1 << A.length; const p=[]; let sum=0; for(let i=0;i<A.length;i++){ if(code & (1<<i)){ sum+=A[i]; p.push(A[i]) } } return {sum,p} } function sumN(A,n,m){ const max=1 << A.length; for(let i=0;i<max;i++){ const {sum,p}=sumByBinaryCode(A,i); if(sum===m){ return p } } return null; }
// 給定一列火車,利用左側的環狀鐵軌對火車車箱進行從新排序,給定初始順序和排序後的順序,寫一個函數,判斷這樣是否可行? function isTrans(o,t){ const q=[]; for(let x of t){ if(q[q.length-1]===x){ q.pop() } let y=null; while(o.length >0 && (y=o.shift()) !== x){ q.unshift(y); } } return q.length === 0; }
優化
function isTrans(o,t){ const q=new Queue(); for(let x of t){ if(q.peek()===x){ q.dequeue() } let y=null; while(o.size()>0 && (y=o.dequeue()) !== x){ q.enqueue(y) } } return q.size()===0 }
// 小蟲子從A到B,只能沿着網格走,每次只能向右或向下。求有多少種走法? function f(x,y){ if(x>0 && y>0){ return f(x-1,y)+f(x,y-1) }else if(x>0){ return f(x-1,y) }else if(y>0){ return f(x,y-1) }else{ return 1 } }
優化
function f(x,y,dp=[]){ if(!dp[y]){ dp[y]=[] } if(dp[y][x] !== undefined){ return dp[y][x] } if(x>0 && y>0){ dp[y][x]= f(x-1,y,dp)+f(x,y-1,dp) }else if(x>0){ dp[y][x]= f(x-1,y,dp) }else if(y>0){ dp[y][x]= f(x,y-1,dp) }else{ dp[y][x]= 1 } return dp[y][x] }