Last active
January 29, 2019 09:02
-
-
Save YaoKaiLun/bbddc33fa9d885e735969f09f74016e1 to your computer and use it in GitHub Desktop.
the practice of javascript
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
/* | |
* 要求:实现一个div滑动的动画,由快至慢5s结束 | |
* 参考:https://developers.google.com/web/fundamentals/design-and-ux/animations/css-vs-javascript?hl=zh-tw | |
*/ | |
function Box() { | |
let startTime = 0 | |
const ACCEL = 30 | |
const TIME = 5 | |
let initSpeed = ACCEL * TIME | |
let testDom = document.querySelector('#test') | |
this.startAnimation = function() { | |
startTime = Date.now() | |
requestAnimationFrame(frameUpdate) | |
} | |
function frameUpdate() { | |
let currentTime = (Date.now() - startTime) / 1000 | |
if (currentTime >=5) return | |
let position = parseInt(initSpeed * currentTime - 1/2 * ACCEL * Math.pow(currentTime, 2)) | |
testDom.style.transform = 'translateX(' + position + 'px)' | |
requestAnimationFrame(frameUpdate) | |
} | |
} | |
let box = new Box() | |
box.startAnimation() |
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
/* | |
* 要求:实现 bind 的 polyfill | |
* 参考:https://github.com/mqyqingfeng/Blog/issues/12 | |
*/ | |
// simple | |
if(!Function.prototype.bind) { | |
Function.prototype.bind = function(context) { | |
let preArgs = [].slice.call(arguments, 1) | |
let self = this | |
return function() { | |
let nextArgs = [].slice.call(arguments) | |
self.apply(context, preArgs.concat(nextArgs)) | |
} | |
} | |
} | |
/* | |
* complex | |
* 上面情况在构造调用前执行 bind 会出现问题,它会永久绑定指定的 this。 而真实情况是,构造函数的优先级高于 bind | |
*/ | |
if(!Function.prototype.bind) { | |
Function.prototype.bind = function(context) { | |
if (typeof this !== 'function') { | |
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); | |
} | |
let preArgs = [].slice.call(arguments, 1) | |
let self = this | |
function fNOP() {} | |
let fBound = function() { | |
let nextArgs = [].slice.call(arguments) | |
self.apply(this instanceof fNOP ? this : context, preArgs.concat(nextArgs)) | |
} | |
fNOP.prototype = this.prototype | |
fBound.prototype = fNOP.prototype | |
return fBound | |
} | |
} |
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 debounce(callback, time) { | |
let timer | |
return function(...args) { | |
clearTimeout(timer) | |
let context = this | |
timer = setTimeout(() => { | |
callback.apply(context, args) | |
}, time) | |
} | |
} | |
// 节流,固定时间 | |
function throttle(callback, time) { | |
let timer | |
let start = +new Date() | |
return function(...args) { | |
clearTimeout(timer) | |
let context = this | |
let now = +new Date() | |
if (now - start >= time) { | |
callback.apply(context, args) | |
start = now | |
} else { | |
timer = setTimeout(function() { | |
callback(...args) | |
}, time) | |
} | |
} | |
} |
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 clone(item) { | |
if (!item) { return item; } // null, undefined values check | |
let types = [ Number, String, Boolean ], result; | |
// normalizing primitives if someone did new String('aaa'), or new Number('444'); | |
types.forEach(function(type) { | |
if (item instanceof type) { | |
result = type(item); | |
} | |
}); | |
if (typeof result == "undefined") { | |
if (Object.prototype.toString.call( item ) === "[object Array]") { | |
result = []; | |
item.forEach(function(child, index, array) { | |
result[index] = clone( child ); | |
}); | |
} else if (typeof item == "object") { | |
// testing that this is DOM | |
if (item.nodeType && typeof item.cloneNode == "function") { | |
result = item.cloneNode( true ); | |
} else if (!item.prototype) { // check that this is a literal | |
if (item instanceof Date) { | |
result = new Date(item); | |
} else { | |
// it is an object literal | |
result = {}; | |
for (let i in item) { | |
result[i] = clone( item[i] ); | |
} | |
} | |
} else { | |
// depending what you would like here, | |
// just keep the reference, or create new object | |
if (false && item.constructor) { | |
// would not advice to do that, reason? Read below | |
result = new item.constructor(); | |
} else { | |
result = item; | |
} | |
} | |
} else { | |
result = item; | |
} | |
} | |
return result; | |
} | |
// 测试数据 | |
let copy = clone({ | |
one : { | |
'one-one' : new String("hello"), | |
'one-two' : ["one", "two", true, "four"] | |
}, | |
two : document.createElement("div"), | |
three : [ | |
{ | |
name : "three-one", | |
number : new Number("100"), | |
obj : new function() { | |
this.name = "Object test"; | |
} | |
} | |
] | |
}) |
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 getStyle(el, styleProp) { | |
var value, defaultView = el.ownerDocument.defaultView; | |
if (defaultView && defaultView.getComputedStyle) { | |
// sanitize property name to css notation (hypen separated words eg. font-Size) | |
styleProp = styleProp.replace(/([A-Z])/g, "-$1").toLowerCase(); | |
return defaultView.getComputedStyle(el, null).getPropertyValue(styleProp); | |
} else if (el.currentStyle) { // IE | |
// sanitize property name to camelCase | |
styleProp = styleProp.replace(/\-(\w)/g, function(str, letter) { | |
return letter.toUpperCase(); | |
}); | |
value = el.currentStyle[styleProp]; | |
// convert other units to pixels on IE | |
if (/^\d+(em|pt|%|ex)?$/i.test(value)) { | |
return (function(value) { | |
var oldLeft = el.style.left, oldRsLeft = el.runtimeStyle.left; | |
el.runtimeStyle.left = el.currentStyle.left; | |
el.style.left = value || 0; | |
value = el.style.pixelLeft + "px"; | |
el.style.left = oldLeft; | |
el.runtimeStyle.left = oldRsLeft; | |
return value; | |
})(value); | |
} | |
return value; | |
} | |
} |
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
// 质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。 | |
function isPrimes(num) { | |
if (num <= 1) return false | |
for (let i = 2, s = Math.sqrt(num); i <= s; i++) { | |
if (num % i === 0) return false | |
} | |
return true | |
} |
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
/* | |
* 实现 promise 的 polyfill | |
* 参考:https://github.com/forthealllight/blog/issues/4 | |
* 要点:由于调用成功后开发者会自己调用 resolve,因此并不需要轮询之类的,来确定执行成功 | |
* 以下只支持异步 Promise 和单个 then 绑定,不支持链式调用 | |
*/ | |
/* | |
* 思路: | |
* 接受一个函数做参数,调用并传回 resolve 和 reject 函数 | |
* 返回一个 then 函数 | |
*/ | |
let p = new Promise(function(resolve, reject) { | |
if(true) { | |
resolve('data') | |
} else { | |
reject('err') | |
} | |
}) | |
// 1.简易版本,支持一个 then | |
p.then(() => {}, () => {}) | |
// 2.支持多个 then | |
p.then(() => {}, () => {}) | |
// 3.支持链式调用 | |
p.then(() => {}, () => {}).then(() => {}, () => {}) | |
// 实现: | |
function Promise2(callback) { | |
let self = this | |
this.status = 'pendding' | |
this.successCallback = null | |
this.failCallback = null | |
function resolve(data) { | |
self.status = 'fulfilled' | |
self.value = data | |
if(self.successCallback) { | |
self.successCallback(data) | |
} | |
} | |
function reject(err) { | |
self.status = 'rejected' | |
self.error = err | |
if(self.failCallback) { | |
this.failCallback(err) | |
} | |
} | |
callback(resolve, reject) | |
} | |
Promise2.prototype.then = function(successCallback, failCallback) { | |
switch(this.status) { | |
case 'pendding': | |
this.successCallback = successCallback | |
this.failCallback = failCallback | |
case 'fulfilled': | |
successCallback(this.value) | |
break | |
case 'rejected': | |
failCallback(this.error) | |
break | |
} | |
} |
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 events = { | |
events: {}, | |
on: function (eventName, fn) { | |
this.events[eventName] = this.events[eventName] || []; | |
this.events[eventName].push(fn); | |
}, | |
off: function(eventName, fn) { | |
if (this.events[eventName]) { | |
for (var i = 0; i < this.events[eventName].length; i++) { | |
if (this.events[eventName][i] === fn) { | |
this.events[eventName].splice(i, 1); | |
break; | |
} | |
}; | |
} | |
}, | |
emit: function (eventName, data) { | |
if (this.events[eventName]) { | |
this.events[eventName].forEach(function(fn) { | |
fn(data); | |
}); | |
} | |
} | |
}; |
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
/* | |
* 要求:数组去重 | |
* 参考:https://stackoverflow.com/questions/9229645/remove-duplicate-values-from-js-array | |
*/ | |
/* | |
* 1. filter 和 indexof | |
* 有性能问题 | |
*/ | |
function unique(arr) { | |
retunr arr.filter(function(item, pos, self) { | |
return self.indexOf(item) == pos; | |
}) | |
} | |
/* | |
* 2. hash table 和 filter | |
* javascript 中的对象键类型为 string,因此 "1" and 1 和被认为是重复的,可通过 es6 的 set 或 map 来优化 | |
*/ | |
function unique(arr) { | |
let hashTable = {} | |
arr.filter(function(item) { | |
return hashTable.hasOwnProperty(item) ? false : (hashTable[item] = true) | |
}) | |
} | |
/* | |
* 3. 先排序后过滤 | |
*/ | |
function unique(arr) { | |
return arr.sort().filter(function(item, pos, ary) { | |
return !pos || item != ary[pos - 1]; | |
}) | |
} | |
/* | |
* 4. es6 | |
*/ | |
function unique(arr) { | |
return [...new Set(arr)] | |
} |
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
/* | |
* 要求:实现一个简单的模板引擎 | |
* 参考:http://blog.jobbole.com/56689/ | |
*/ | |
let template = "<p>你好,我是<%this.name%>,</p><i><%this.alias%></i>" | |
let data = { | |
name: '姚凯伦', | |
alias: 'ykl' | |
} | |
function templateEngine(tmpl, data) { | |
let sentence = convertTmplToSentence(tmpl, data) | |
return new Function(sentence).apply(data) | |
} | |
function convertTmplToSentence(tmpl, data) { | |
let regex = /<%([^%>]+)?%>/g | |
let grammarRegex = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g | |
let code = 'var r=[];\n' | |
/* | |
* 三种情况: | |
* 字符串,以普通字符串形式 push 到 code | |
* 变量 <%%>,以变量形式 push 到 code | |
* 语句 <%if|for|else|switch|case|break|{|})%>,直接执行 | |
*/ | |
let cursor = 0 | |
let match | |
while(match = regex.exec(tmpl)) { | |
let str = tmpl.slice(cursor, match.index) | |
code += 'r.push("' + str.replace(/"/g, '\\"') + '");\n' | |
if (match[1].match(grammarRegex)) { | |
code += match[1] + '\n' | |
} else { | |
code += 'r.push(' + match[1] + ');\n' | |
} | |
cursor = match.index + match[0].length; | |
} | |
code += 'r.push("' + tmpl.substr(cursor, tmpl.length - cursor) +'");\n' | |
code += 'return r.join("");'; | |
return code.replace(/[\r\t\n]/g, '') | |
} | |
console.log('result', templateEngine(template, data)) |
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
/* | |
* 要求:求字符串的字节长度 | |
* 参考:http://www.ruanyifeng.com/blog/2014/12/unicode.html | |
*/ | |
// 方法一: | |
function byteLength(str) { | |
let len = str.length; | |
for (let i = len - 1; i >= 0; i--) { | |
let code = str.charCodeAt(i); | |
if (code > 0x7f && code <= 0x7ff) len++; | |
else if (code > 0x7ff && code <= 0xffff) len += 2; | |
if (code >= 0xDC00 && code <= 0xDFFF) i--; // trail surrogate (超过两个字节会被拆分为两个) | |
} | |
return s; | |
} | |
// 方法二: | |
new Blob(['𠮷']).size; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment