├── .DS_Store ├── .idea ├── $CACHE_FILE$ ├── .gitignore ├── Code-for-JavaScript.iml ├── dictionaries ├── jsLibraryMappings.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── Code ├── apply手写实现.js ├── bind手写实现.js ├── call手写实现.js ├── es5实现类的继承.js ├── es5实现面向对象继承.js ├── es6中的面向对象.js ├── es6中类的继承.js ├── events.js ├── js并发.js ├── js并发2.js ├── parseQueryString.js ├── proxy代理沙箱.js ├── 函数防抖与节流.md ├── 完美深拷贝.js ├── 尾递归优化实现斐波那契数列.js ├── 快照沙箱.js ├── 手写Jsonp.md ├── 数组扁平化-es5.js ├── 数组扁平化-es6.js ├── 数组结构转树形结构.js ├── 数组负数索引.js ├── 用迭代器实现斐波那契数列.js └── 类型判断.js ├── README.md └── demo.html /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fltenwall/Code-for-JavaScript/427dea92e07098498a0119d2c44ac81ea5f6dc50/.DS_Store -------------------------------------------------------------------------------- /.idea/$CACHE_FILE$: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Angular 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.idea/Code-for-JavaScript.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/dictionaries: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Code/apply手写实现.js: -------------------------------------------------------------------------------- 1 | var name = 'flten'; 2 | var obj = { 3 | name: '轩灵' 4 | }; 5 | 6 | function fn(a, b, c) { 7 | console.log(a + b + c + this.name); 8 | } 9 | 10 | Function.prototype.myApply = function(obj,arr){ 11 | //传的不是对象,强制转为对象;不传,默认window 12 | var obj = obj ? Object(obj):window; 13 | 14 | if(!arr){ 15 | obj.fn() 16 | }else{ 17 | var args = []; 18 | for(var i = 0,len=arr.length;i对象 15 | Animal.prototype.cat = function(){ 16 | console.log('a'); 17 | } 18 | 19 | //prototype上的属性(公共属性) 20 | Animal.prototype.num1 = 1; 21 | console.log(animal.type); 22 | console.log(animal.hasOwnProperty('type')); 23 | 24 | //每一个对象都有一个__proto__属性,指向父类的prototype 25 | console.log(animal.__proto__ === Animal.prototype);//true 26 | 27 | //每个类的prototype都有一个constructor属性,指向该类 28 | console.log(animal.constructor);//[Function:Animal] 29 | console.log(animal.__proto__.constructor === animal.constructor );//true 30 | 31 | console.log(animal.__proto__.__proto__.__proto__ === null);//true 32 | console.log(animal.__proto__.__proto__ === Object.prototype);//true 33 | console.log(Animal.prototype.__proto__ === Object.prototype);//true 34 | console.log(Object.prototype.__proto__);//null 35 | 36 | animal.cat();//a 37 | animal.say();//say 38 | 39 | animal.cat = function(){ 40 | console.log('cat..'); 41 | } 42 | animal.cat();//cat.. 43 | 44 | let animal2 = new Animal(); 45 | animal2.cat();//a 46 | 47 | console.log(animal.num1);//1 48 | 49 | Animal();//构造函数作为普通函数调用 50 | 51 | /* 52 | 53 | 1.类 54 | 静态属性和静态方法 55 | (1)静态属性和静态方法能够被实例对象继承,但不能被修改 56 | 57 | 2.原型(prototype) 58 | (1)类中的prototype属性指向自己的原型对象(独立空间) 59 | (2)类的实例对象通过__proto__属性指向类的原型对象,可以通过原型链向上访问原型上的属性和方法,但不能修改原型上的属性和方法 60 | 61 | 3.实例 62 | 成员属性和成员方法 63 | 64 | */ -------------------------------------------------------------------------------- /Code/es6中的面向对象.js: -------------------------------------------------------------------------------- 1 | class Animal{//es6提供了类,只能new 2 | //实现抽象类 3 | constructor(){ 4 | 5 | // if(new.target === Animal){ 6 | // throw new Error("not new Animal"); 7 | // } 8 | 9 | //实例上的属性和方法 10 | this._type = "animal"; 11 | this.age = 20; 12 | } 13 | 14 | //更改实例属性 15 | get type(){ 16 | //这里的this指向调用者,即实例对象 17 | return this._type; 18 | } 19 | 20 | set type(newType){ 21 | this._type = newType; 22 | } 23 | 24 | //报错 25 | // get age(){ 26 | // return this.age; 27 | // } 28 | 29 | //类的原型prototype对象上的方法 30 | eat(){ 31 | console.log('eat..'); 32 | } 33 | 34 | //类的原型prototype对象上的属性 35 | get a(){ 36 | return 100; 37 | } 38 | 39 | //es6中不支持静态属性 40 | // static a = 10;//报错 41 | 42 | //静态属性 43 | static get num(){ 44 | return "num"; 45 | } 46 | 47 | //静态方法 48 | static jump(){ 49 | return "jump.." 50 | } 51 | 52 | // a = 1;//实例上的属性,es7中的语法,node环境还无法使用 53 | } 54 | 55 | let animal = new Animal(); 56 | 57 | //调用原型上的方法 58 | animal.eat();//eat.. 59 | 60 | //调用原型上的属性 61 | console.log(animal.a);//100 62 | 63 | //调用类的静态属性和静态方法 64 | console.log(Animal.num);//num 65 | console.log(Animal.jump());//jump 66 | 67 | //使用get和set修改后的实例属性 68 | animal.type = "dog"; 69 | console.log(animal.type);//dog 70 | 71 | console.log(animal.age); 72 | 73 | // Animal();//直接调用报错 74 | 75 | //实现class只能new的类似功能 76 | function Person(){ 77 | 78 | if(!(this instanceof Person)){ 79 | throw new Error("not new"); 80 | } 81 | 82 | }; 83 | // Person();//报错 84 | -------------------------------------------------------------------------------- /Code/es6中类的继承.js: -------------------------------------------------------------------------------- 1 | class Animal{//es6提供了类,只能new 2 | //实现抽象类 3 | constructor(){ 4 | 5 | // if(new.target === Animal){ 6 | // throw new Error("not new Animal"); 7 | // } 8 | 9 | //实例上的属性和方法 10 | this._type = "animal"; 11 | this.age = 20; 12 | } 13 | 14 | //类的原型prototype对象上的方法 15 | eat(){ 16 | console.log('eat..'); 17 | } 18 | 19 | //静态属性 20 | static get num(){ 21 | return "num"; 22 | } 23 | 24 | } 25 | 26 | /* 27 | (1)父类静态属性和静态方法的继承 28 | Tiger.__proto__ = Animal;//改变Tiger的__proto__指向,修改其父类的原型指向,实现静态属性和静态方法的继承 29 | (2)父类原型上的属性和实例方法的继承 30 | Tiger.prototype = Object.create(Animal.prototype); 31 | (3)父类实例属性和实例方法的继承 32 | Animal.call(this); 33 | */ 34 | class Tiger extends Animal{ 35 | constructor(){//使用this之前必须调用super 36 | //实例属性和实例方法 37 | super();//Animal.call(this) 38 | }; 39 | 40 | static parentNum(){ 41 | return super.num;//super指向父类自身 42 | }; 43 | 44 | eat(){ 45 | super.eat();//super指向父类的原型 46 | } 47 | } 48 | 49 | let tiger = new Tiger('tiger1'); 50 | 51 | //调用实例属性 52 | console.log(tiger.age);//20 53 | //调用原型方法 54 | tiger.eat();//eat.. 55 | //调用静态方法 56 | console.log(Tiger.parentNum());//num -------------------------------------------------------------------------------- /Code/events.js: -------------------------------------------------------------------------------- 1 | function EventEmitter(){ 2 | this._events = {}; 3 | } 4 | 5 | EventEmitter.prototype.on = function(eventName,callback){ 6 | // if(eventName !== 'newListener'){ 7 | // this._events['newListener'] ? this._events['newListener'].forEach(fn => fn(eventName)) : void 0 8 | // } 9 | if(!this._events){ 10 | // this._events = {};这种方式有原型链 11 | this._events = Object.create(null); 12 | } 13 | if(this._events[eventName]){ 14 | this._events[eventName].push(callback); 15 | }else{ 16 | this._events[eventName] = [callback]; 17 | } 18 | } 19 | 20 | EventEmitter.prototype.once = function(eventName,callback){ 21 | function one(){ 22 | callback(...arguments); 23 | this.off(eventName,one); 24 | } 25 | one.link = callback; 26 | this.on(eventName,one); 27 | } 28 | 29 | EventEmitter.prototype.off = function(eventName,callback){ 30 | if(this._events[eventName]){ 31 | this._events[eventName] = this._events[eventName].filter(fn => { 32 | fn != callback && fn.link != callback //为once做处理 33 | }) 34 | } 35 | } 36 | 37 | EventEmitter.prototype.emit = function(eventName){ 38 | if(this._events[eventName]){ 39 | this._events[eventName].forEach(fn => { 40 | fn.call(this,...arguments); 41 | }); 42 | } 43 | } 44 | 45 | module.exports = EventEmitter; -------------------------------------------------------------------------------- /Code/js并发.js: -------------------------------------------------------------------------------- 1 | const tasks = [ 2 | () => new Promise((resolve) => setTimeout(resolve,1000)), 3 | () => Promise.resolve('foo'), 4 | () => Promise.reject(new Error('aaa')), 5 | () => 'bar', 6 | () => new Promise((resolve) => setTimeout(resolve,1000)), 7 | () => Promise.resolve('eoo'), 8 | () => Promise.reject(new Error('bbb')), 9 | () => 'far', 10 | ]; 11 | 12 | function dispatch(tasks, concurrency, done){ 13 | const tasksList = tasks; 14 | const result = { 15 | resolved : [], 16 | rejected : [], 17 | } 18 | const runTime = []; 19 | let flag = null; 20 | 21 | function resolve(res) {result.resolved.push(res)}; 22 | function rejected(err) {result.rejected.push(err)}; 23 | 24 | async function handlePromise(task){ 25 | const runner = Promise.resolve(task()).then(resolve).catch(rejected); 26 | runTime.push(runner); 27 | await runner; 28 | console.log('执行完了:',task); 29 | walk(1); 30 | } 31 | 32 | function walk(c) { 33 | if(tasks.length === 0 && !flag){ 34 | console.log('runTime',runTime); 35 | return flag = Promise.all(runTime).finally(() => { 36 | done(result) 37 | }) 38 | } 39 | tasksList.splice(0,c).forEach(handlePromise); 40 | } 41 | 42 | walk(concurrency); 43 | } 44 | 45 | function dispatcher(tasks, concurrency) { 46 | return new Promise(function(resolve,reject){ 47 | dispatch(tasks, concurrency, resolve); 48 | }) 49 | } 50 | 51 | dispatcher(tasks,3).then(res => console.log('res',res)); 52 | 53 | /* 54 | 55 | 执行完了: [Function (anonymous)] 56 | 执行完了: [Function (anonymous)] 57 | 执行完了: [Function (anonymous)] 58 | 执行完了: [Function (anonymous)] 59 | 执行完了: [Function (anonymous)] 60 | 执行完了: [Function (anonymous)] 61 | runTime [ 62 | Promise { }, 63 | Promise { undefined }, 64 | Promise { undefined }, 65 | Promise { undefined }, 66 | Promise { }, 67 | Promise { undefined }, 68 | Promise { undefined }, 69 | Promise { undefined } 70 | ] 71 | 执行完了: [Function (anonymous)] 72 | 执行完了: [Function (anonymous)] 73 | 74 | res { 75 | resolved: [ 'foo', 'bar', 'eoo', 'far', undefined, undefined ], 76 | rejected: [Error: aaa, Error: bbb] 77 | } 78 | */ -------------------------------------------------------------------------------- /Code/js并发2.js: -------------------------------------------------------------------------------- 1 | const tasks = [ 2 | () => new Promise(() => setTimeout(()=>{console.log('1000');return 1000},1000)), 3 | () => Promise.resolve(function fn1(){console.log('foo');return 'foo'}), 4 | () => Promise.reject(new Error('aaa')), 5 | () => 'bar', 6 | () => new Promise(() => setTimeout(()=>{console.log('2000');return 2000},2000)), 7 | () => new Promise(() => setTimeout(()=>{console.log('1000');return 1000},1000)), 8 | () => new Promise(() => setTimeout(()=>{console.log('3000');return 3000},3000)), 9 | () => new Promise(() => setTimeout(()=>{console.log('1000');return 1000},1000)), 10 | () => Promise.resolve('eoo'), 11 | () => Promise.reject(new Error('bbb')), 12 | () => 'far', 13 | () => 'koa', 14 | () => 'express', 15 | ]; 16 | 17 | function dispatch(tasks, concurrency, done){ 18 | const tasksList = tasks; 19 | const result = { 20 | resolved : [], 21 | rejected : [], 22 | } 23 | const runTime = []; 24 | let flag = null; 25 | 26 | function resolve(res) {result.resolved.push(res)}; 27 | function rejected(err) {result.rejected.push(err)}; 28 | 29 | async function handlePromise(task){ 30 | const runner = Promise.resolve(task()).then(resolve).catch(rejected); 31 | runTime.push(runner); 32 | await runner; 33 | console.log('执行完了:',task); 34 | walk(1); 35 | } 36 | 37 | function walk(c) { 38 | if(tasks.length === 0 && !flag){ 39 | console.log('runTime',runTime); 40 | return flag = Promise.all(runTime).finally(() => { 41 | done(result) 42 | }) 43 | } 44 | tasksList.splice(0,c).forEach(handlePromise); 45 | } 46 | 47 | walk(concurrency); 48 | } 49 | 50 | function dispatcher(tasks, concurrency) { 51 | return new Promise(function(resolve,reject){ 52 | dispatch(tasks, concurrency, resolve); 53 | }) 54 | } 55 | 56 | dispatcher(tasks,3).then(res => console.log('res',res)); -------------------------------------------------------------------------------- /Code/parseQueryString.js: -------------------------------------------------------------------------------- 1 | // 解析路径参数 2 | const parseQueryString = (string) => { 3 | if(Object.is(typeof string, 'string')){ 4 | string = String(string); 5 | } 6 | if(!string || !string.length) return {}; 7 | const resObj = {}; 8 | const splitArr = str.split('&'); 9 | splitArr.forEach(item => { 10 | const [key, val] = item.split('='); 11 | if(resObj[key]){ 12 | if(Array.isArray(resObj[key])){ 13 | resObj[key].push(val); 14 | }else { 15 | resObj[key] = [resObj[key], val]; 16 | } 17 | }else{ 18 | resObj[key] = val; 19 | } 20 | }) 21 | return resObj; 22 | } 23 | 24 | const str = 'a=1&a=2&a=3&b=2&c=3&d=4'; 25 | const res = parseQueryString(str); // {a:['1','2','3'],b:'2',c:'3',d:'4'} 26 | console.log(res); -------------------------------------------------------------------------------- /Code/proxy代理沙箱.js: -------------------------------------------------------------------------------- 1 | class ProxySandbox{ 2 | constructor(){ 3 | const rawWindow = window; 4 | const fakeWindow = {}; 5 | const proxy = new Proxy(fakeWindow,{ 6 | set(target,p,value){ 7 | target[p] = value; 8 | return true 9 | }, 10 | get(target,p){ 11 | return target[p] || rawWindow[p]; 12 | } 13 | }) 14 | this.proxy = proxy; 15 | } 16 | } 17 | 18 | const sandbox1 = new ProxySandbox(); 19 | const sandbox2 = new ProxySandbox(); 20 | window.a = 1; 21 | ( ( window ) => { 22 | window.a = 'hello'; 23 | console.log(window.a) 24 | } )(sandbox1.proxy) 25 | 26 | ( ( window ) => { 27 | window.a = 'hello'; 28 | console.log(window.a) 29 | } )(sandbox2.proxy) -------------------------------------------------------------------------------- /Code/函数防抖与节流.md: -------------------------------------------------------------------------------- 1 | ### 防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时 2 | ```javascript 3 | function debounce(fn, delay) { 4 | var timer; 5 | return function () { 6 | var _this = this; // 保存函数的this指向 7 | var args = arguments; 8 | //每次触发事件时都取消之前的延时调用方法 9 | if (timer) { 10 | clearTimeout(timer); 11 | } 12 | timer = setTimeout(function () { 13 | fn.apply(_this, args); 14 | }, delay); 15 | }; 16 | } 17 | 18 | //测试用例 19 | function test(e, content) { 20 | console.log(e, content); 21 | } 22 | var testFn = debounce(test, 1000); // 防抖函数 23 | document.onmousemove = function (e) { 24 | testFn(e, 'debounce'); // 给防抖函数传参 25 | } 26 | ``` 27 | 28 | 29 | ### 节流:限制函数一段时间内只能执行一次 30 | ```javascript 31 | function throttle(fn, delay) { 32 | var timer; 33 | return function () { 34 | var _this = this; //保存函数的this指向 35 | var args = arguments; 36 | //每次触发事件时都判断当前是否有等待执行的延时函数 37 | if (timer) { 38 | return; 39 | } 40 | timer = setTimeout(function () { 41 | fn.apply(_this, args); 42 | timer = null; 43 | }, delay) 44 | } 45 | } 46 | 47 | function test(e, content) { 48 | console.log(e, content); 49 | } 50 | var testFn = throttle(testThrottle, 1000); // 节流函数 51 | document.onmousemove = function (e) { 52 | testFn(e, 'throttle'); // 给节流函数传参 53 | } 54 | ``` 55 | -------------------------------------------------------------------------------- /Code/完美深拷贝.js: -------------------------------------------------------------------------------- 1 | //判断是否为复杂数据类型 2 | const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && (obj !== null); 3 | 4 | //利用 WeekMap() 的键对自己所引用对象的引用都是弱引用的特性,在没有其他引用和该键引用同一对象的情况下,这个对象将会被垃圾回收 5 | //为了解决循环引用的问题,设置一个哈希表存储已拷贝过的对象进行循环检测,当检测到当前对象已存在于哈希表中时,取出该值并返回即可 6 | const deepClone = function(obj,hash = new WeakMap()){ 7 | //查哈希表,防止循环拷贝。如果成环了(对象循环引用),参数obj = obj.loop = 最初的obj,则会在WeakMap中找到第一次放入的obj提前返回第一次放入WeakMap的cloneObj,解决对象循环引用的问题 8 | if(hash.has(obj)) return hash.get(obj); 9 | 10 | //如果参数为Date, RegExp, Set, Map, WeakMap, WeakSet等引用类型,则直接生成一个新的实例 11 | let type = [Date,RegExp,Set,Map,WeakMap,WeakSet]; 12 | if(type.includes(obj.constructor)) return new obj.constructor(obj); 13 | 14 | //遍历传入参数所有属性描述符 15 | let allDesc = Object.getOwnPropertyDescriptors(obj); 16 | //继承原型 17 | let cloneObj = Object.create(Object.getPrototypeOf(obj),allDesc); 18 | 19 | // 获取所有 Symbol 类型键 20 | let symKeys = Object.getOwnPropertySymbols(obj); 21 | // 拷贝 Symbol 类型键对应的属性 22 | if (symKeys.length > 0) { 23 | symKeys.forEach(symKey => { 24 | cloneObj[symKey] = isComplexDataType(obj[symKey]) ? deepClone(obj[symKey], hash) : obj[symKey] 25 | }) 26 | } 27 | 28 | // 哈希表设值 29 | hash.set(obj,cloneObj); 30 | 31 | //Reflect.ownKeys(obj)拷贝不可枚举属性和符号类型 32 | for(let key of Reflect.ownKeys(obj)){ 33 | // 如果值是引用类型并且非函数则递归调用deepClone 34 | cloneObj[key] = 35 | (isComplexDataType(obj[key]) && typeof obj[key] !== 'function') ? deepClone(obj[key],hash) : obj[key]; 36 | } 37 | return cloneObj; 38 | }; 39 | 40 | let obj = { 41 | arr : [0,1,2,3,4,5,6] 42 | }; 43 | 44 | let obj2 = deepClone(obj); 45 | obj2.str = 'flten'; 46 | console.log(obj,obj2);//{arr: [0, 1, 2, 3, 4, 5, 6],str: "flten"} 47 | 48 | console.log('-------------'); 49 | 50 | //处理循环引用测试 51 | let a = { 52 | name: "lk", 53 | course: { 54 | vue: "Vue.js", 55 | react: "React.js" 56 | }, 57 | a1: undefined, 58 | a2: null, 59 | a3: 123, 60 | a4: NaN 61 | }; 62 | 63 | //对象循环引用 64 | a.circleRef = a; 65 | 66 | let b = deepClone(a); 67 | console.log(b); 68 | // { 69 | // name: "lk", 70 | // a1: undefined, 71 | // a2: null, 72 | // a3: 123, 73 | // a4: NaN, 74 | // course: {vue: "Vue.js",react: "React.js"}, 75 | // circleRef: {name: "lk",a1: undefined, a2: null, a3: 123, a4:NaN …} 76 | // } 77 | -------------------------------------------------------------------------------- /Code/尾递归优化实现斐波那契数列.js: -------------------------------------------------------------------------------- 1 | // 基础框架 2 | function fib(n) { 3 | return fibImpl(0, 1, n); 4 | } 5 | 6 | // 执行递归 7 | function fibImpl(a, b, n) { 8 | if (n === 0) { 9 | return a; 10 | } 11 | return fibImpl(b, a + b, n - 1); 12 | } -------------------------------------------------------------------------------- /Code/快照沙箱.js: -------------------------------------------------------------------------------- 1 | //快照沙箱 2 | class SnapshotSandbox{ 3 | constructor(){ 4 | this.proxy = window; 5 | this.modifyPropMap = {}; 6 | this.active(); 7 | } 8 | // 激活 9 | active(){ 10 | this.windowSnapshot = {}; 11 | for(const prop in window){ 12 | if(window.hasOwnProperty(prop)){ 13 | this.windowSnapshot[prop] = window[prop]; 14 | } 15 | } 16 | Object.keys(this.windowSnapshot).forEach(p => { 17 | window[p] = this.modifyPropMap[p]; 18 | }) 19 | } 20 | 21 | // 失效 22 | inactive(){ 23 | for(const prop in window){ 24 | if(window.hasOwnProperty(prop)){ 25 | if(window[prop] !== this.windowSnapshot[prop]){ 26 | this.modifyPropMap[prop] = window[prop]; 27 | window[prop] = this.windowSnapshot[prop]; 28 | } 29 | } 30 | } 31 | } 32 | } 33 | 34 | let sandbox = new SnapshotSandbox(); 35 | 36 | ((window) => { 37 | window.a = 1; 38 | window.b = 2; 39 | console.log(window.a,window.b); 40 | sandbox.inactive(); 41 | console.log(window.a,window.b); 42 | sandbox.active(); 43 | console.log(window.a,window.b); 44 | })(sandbox.proxy) -------------------------------------------------------------------------------- /Code/手写Jsonp.md: -------------------------------------------------------------------------------- 1 | jsonp 2 | ```javascript 3 | /** 4 | * jsonp获取请求数据 5 | * @param {object}options 6 | */ 7 | function jsonp(options) { 8 | // console.log(options); 9 | // 1. 产生不同的函数名(函数名随机) 10 | let callBackName = 'itLike' + Math.random().toString().substr(2)+ Math.random().toString().substr(2); 11 | // console.log(callBackName); 12 | 13 | // 2. 产生一个全局函数 14 | window[callBackName] = function (params) { 15 | // console.log(params); 16 | // console.log(options.success); 17 | if(params !== null){ 18 | options.success(params); 19 | }else{ 20 | options.failure(params); 21 | } 22 | 23 | // 2.1 删除当前脚本标签 24 | scriptE.remove(); 25 | // 2.2 将创建的全局函数设为null 26 | window[callBackName] = null; 27 | }; 28 | 29 | // 3. 取出url地址 30 | let jsonpUrl; 31 | if(options.data !== undefined){ 32 | jsonpUrl = options.url + '?' + options.data + '&callBack=' + callBackName; 33 | }else { 34 | jsonpUrl = options.url + '?callBack=' + callBackName; 35 | } 36 | // console.log(jsonpUrl); 37 | 38 | // 4. 创建script标签 39 | let scriptE = document.createElement('script'); 40 | scriptE.src = jsonpUrl; 41 | document.body.appendChild(scriptE); 42 | } 43 | ``` 44 | 45 | 46 | 服务端(express) 47 | ```javascript 48 | router.get('/api/v1', function(req, res, next) { 49 | res.json({ 50 | 'name': '轩灵', 51 | 'address': '北京', 52 | 'intro': 'fltenwall' 53 | }); 54 | }); 55 | ``` 56 | 57 | 58 | 调用jsonp 59 | ```javascript 60 | btn.addEventListener('click', ()=>{ 61 | jsonp({ 62 | url: 'http://localhost:3000/api/v1', 63 | data: 'name=轩灵&age=24', 64 | success: function (data) { 65 | console.log(data); 66 | }, 67 | failure:function(data){ 68 | console.log(数据请求失败); 69 | } 70 | }); 71 | }); 72 | ``` 73 | -------------------------------------------------------------------------------- /Code/数组扁平化-es5.js: -------------------------------------------------------------------------------- 1 | function flatten(arr){ 2 | let result = []; 3 | for(let i=0,len=arr.length;i Array.isArray(item))){ 3 | arr = [].concat(...arr); 4 | } 5 | return arr; 6 | } 7 | 8 | let oldArr = [1,[2,3],[3,4,5]] 9 | let newArr = flatten(oldArr); 10 | console.log(newArr) -------------------------------------------------------------------------------- /Code/数组结构转树形结构.js: -------------------------------------------------------------------------------- 1 | 2 | //代码 3 | const convert = (list) => { 4 | const map = list.reduce((res,v)=>{ 5 | res[v.id] = v; 6 | return res; 7 | },{}) 8 | 9 | const res = []; 10 | for(let item of list){ 11 | if(item.parent === null){ 12 | res.push(item); 13 | continue; 14 | } 15 | if(item.parent in map){ 16 | const parent = map[item.parent]; 17 | parent.children = parent.children || []; 18 | parent.children.push(item); 19 | } 20 | } 21 | return res; 22 | } 23 | 24 | //目标数组 25 | var arr = [ 26 | {'id' : 3,'parent' : 2}, 27 | {'id' : 1,'parent' : null}, 28 | {'id' : 2,'parent' : 1} 29 | ] 30 | 31 | //期望结果 32 | var obj = { 33 | id : 1, 34 | parent : null, 35 | child : { 36 | id : 2, 37 | parent : 1, 38 | child : { 39 | id : 3, 40 | parent : 2 41 | } 42 | } 43 | } 44 | 45 | convert(arr) -------------------------------------------------------------------------------- /Code/数组负数索引.js: -------------------------------------------------------------------------------- 1 | function createArray(...element){ 2 | const handler = { 3 | get(target,propKey,receiver){ 4 | const index = Number(propKey); 5 | if(index < 0){ 6 | propKey = String(target.length + index) 7 | } 8 | return Reflect.get(target,propKey,receiver) 9 | } 10 | } 11 | 12 | let target = []; 13 | target.push(...element); 14 | return new Proxy(target,handler) 15 | } 16 | 17 | let arr = createArray('a','b','c'); 18 | arr[-2] -------------------------------------------------------------------------------- /Code/用迭代器实现斐波那契数列.js: -------------------------------------------------------------------------------- 1 | function * fabonacciSequence(){ 2 | let [x, y] = [0, 1]; 3 | for(;;){ 4 | yield y; 5 | [x,y] = [y,x+y]; 6 | } 7 | }; 8 | function fibonacci(n){ 9 | for(let f of fabonacciSequence()){ 10 | if(n-- <= 0) return f; 11 | } 12 | }; 13 | fibonacci(20); // 10946 14 | 15 | function * take(n, iterable){ 16 | let it = iterable[Symbol.iterator](); 17 | while(n-- > 0){ 18 | let next = it.next(); 19 | if(next.done) return; 20 | else yield next.value; 21 | } 22 | }; 23 | [...take(5, fabonacciSequence())] // [1, 1, 2, 3, 5] 24 | -------------------------------------------------------------------------------- /Code/类型判断.js: -------------------------------------------------------------------------------- 1 | function typeOf(obj){ 2 | return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase() 3 | } 4 | 5 | typeOf([]) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Code-for-JavaScript 2 | 3 | 手写各种javacripts实现 4 | 5 | 1. [函数防抖与节流](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/函数防抖与节流.js) 6 | 2. [快照沙箱](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/快照沙箱.js) 7 | 3. [类型判断](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/类型判断.js) 8 | 4. [手写Jsonp](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/手写Jsonp.js) 9 | 5. [数组扁平化-es5](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/数组扁平化-es5.js) 10 | 6. [数组扁平化-es6.js](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/数组扁平化-es6.js) 11 | 7. [数组负数索引](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/数组负数索引.js) 12 | 8. [数组结构转树形结构](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/数组结构转树形结构.js) 13 | 9. [完美深拷贝](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/完美深拷贝.js) 14 | 10. [尾递归优化实现斐波那契数列](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/尾递归优化实现斐波那契数列.js) 15 | 11. [用迭代器实现斐波那契数列](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/用迭代器实现斐波那契数列.js) 16 | 12. [apply手写实现](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/apply手写实现.js) 17 | 13. [bind手写实现](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/bind手写实现.js) 18 | 14. [call手写实现](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/call手写实现.js) 19 | 15. [es5实现类的继承](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/es5实现类的继承.js) 20 | 16. [es5实现面向对象继承](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/es5实现面向对象继承.js) 21 | 17. [es6中的面向对象](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/es6中的面向对象.js) 22 | 18. [es6中类的继承](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/es6中类的继承.js) 23 | 19. [events](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/events.js) 24 | 20. [js并发](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/js并发.js) 25 | 21. [js并发2](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/js并发2.js) 26 | 22. [parseQueryString](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/parseQueryString.js) 27 | 23. [proxy代理沙箱](https://github.com/fltenwall/Code-for-JavaScript/blob/master/Code/proxy代理沙箱.js) -------------------------------------------------------------------------------- /demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 38 | 39 | --------------------------------------------------------------------------------