├── .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 |
5 |
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 |
--------------------------------------------------------------------------------