diff --git "a/CSS3\345\261\236\346\200\247\351\200\237\346\237\245\350\241\250.pdf" "b/CSS3\345\261\236\346\200\247\351\200\237\346\237\245\350\241\250.pdf" new file mode 100644 index 0000000..60066e8 Binary files /dev/null and "b/CSS3\345\261\236\346\200\247\351\200\237\346\237\245\350\241\250.pdf" differ diff --git "a/GitHub\345\205\245\351\227\250\344\270\216\345\256\236\350\267\265.pdf" "b/GitHub\345\205\245\351\227\250\344\270\216\345\256\236\350\267\265.pdf" new file mode 100644 index 0000000..5229b5b Binary files /dev/null and "b/GitHub\345\205\245\351\227\250\344\270\216\345\256\236\350\267\265.pdf" differ diff --git "a/HTML5\344\270\216CSS3\345\237\272\347\241\200\346\225\231\347\250\213\357\274\210\347\254\2548\347\211\210\357\274\211\344\270\255\346\226\207\351\253\230\346\270\205\347\211\210.pdf" "b/HTML5\344\270\216CSS3\345\237\272\347\241\200\346\225\231\347\250\213\357\274\210\347\254\2548\347\211\210\357\274\211\344\270\255\346\226\207\351\253\230\346\270\205\347\211\210.pdf" new file mode 100755 index 0000000..adeed75 Binary files /dev/null and "b/HTML5\344\270\216CSS3\345\237\272\347\241\200\346\225\231\347\250\213\357\274\210\347\254\2548\347\211\210\357\274\211\344\270\255\346\226\207\351\253\230\346\270\205\347\211\210.pdf" differ diff --git "a/HTML5\344\270\216CSS3\346\235\203\345\250\201\346\214\207\345\215\227\347\254\254\344\272\214\347\211\210.pdf" "b/HTML5\344\270\216CSS3\346\235\203\345\250\201\346\214\207\345\215\227\347\254\254\344\272\214\347\211\210.pdf" new file mode 100644 index 0000000..904fd9c Binary files /dev/null and "b/HTML5\344\270\216CSS3\346\235\203\345\250\201\346\214\207\345\215\227\347\254\254\344\272\214\347\211\210.pdf" differ diff --git "a/HTML5\346\240\207\347\255\276\345\210\227\350\241\250.pdf" "b/HTML5\346\240\207\347\255\276\345\210\227\350\241\250.pdf" new file mode 100644 index 0000000..c3ee2ec Binary files /dev/null and "b/HTML5\346\240\207\347\255\276\345\210\227\350\241\250.pdf" differ diff --git "a/HTTP\345\215\217\350\256\256\344\270\255\346\226\207\347\211\210.pdf" "b/HTTP\345\215\217\350\256\256\344\270\255\346\226\207\347\211\210.pdf" new file mode 100644 index 0000000..e46e963 Binary files /dev/null and "b/HTTP\345\215\217\350\256\256\344\270\255\346\226\207\347\211\210.pdf" differ diff --git "a/HTTP\345\215\217\350\256\256\345\210\206\346\236\220.pdf" "b/HTTP\345\215\217\350\256\256\345\210\206\346\236\220.pdf" new file mode 100644 index 0000000..7a05508 Binary files /dev/null and "b/HTTP\345\215\217\350\256\256\345\210\206\346\236\220.pdf" differ diff --git "a/HTTP\345\215\217\350\256\256\350\257\246\350\247\243.pdf" "b/HTTP\345\215\217\350\256\256\350\257\246\350\247\243.pdf" new file mode 100644 index 0000000..5891d04 Binary files /dev/null and "b/HTTP\345\215\217\350\256\256\350\257\246\350\247\243.pdf" differ diff --git "a/JavaScript\344\270\255Array\347\232\204\344\270\200\344\272\233\346\223\215\344\275\234.md" "b/JavaScript\344\270\255Array\347\232\204\344\270\200\344\272\233\346\223\215\344\275\234.md" new file mode 100644 index 0000000..b2f8957 --- /dev/null +++ "b/JavaScript\344\270\255Array\347\232\204\344\270\200\344\272\233\346\223\215\344\275\234.md" @@ -0,0 +1,45 @@ +# JavaScript中Array的一些操作 +## 1、判断一个对象是否为数组 +``` +function isArray(a) { + return Array.isArray ? Array.isArray(a) : Object.prototype.toString.call(a) === '[object Array]'; +} +``` +  Array.isArray是ES6新增的一个方法,考虑不是所有浏览器都支持ES5,先做判断,如果浏览器支持Array.isArray()则使用,否则使用Object.prototype.toString.call()方法,注意这里说的toString()是Object原型链上的toString()方法,和obj.toString()是两码事。Object.prototype.toString.call()只会返回[Object [[Class]]]这种形式。 +## 2、数组虑重 +  一共总结了四种方法,其中前面两种实际编码中不会用到,但是面试的时候可以提一下。 +#### 双重循环 +  就不多说了,挨个儿比较,时间复杂度为O(n^2)。 +#### 排序后遍历 +  先对数组排序,由于数组已经有序,只需要检查数组中第i个元素与新的结果数组中最后一个元素是否相等即可,如果不相等,则放到新的结果数组中,这种方法的时间复杂度为O(n),但是还要考虑排序的消耗,所以同样不可取。这两种方法比较简单,均不上代码。 +#### Hash的方法 +  散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。 +  把Hash表用于数组去重就在于,把数组的值依次存入Hash表的Key值,Value值可以存储Key出现的次数。存取的时候产生冲突的话,忽略该元素,反之把该元素存入新数组。该方法时间复杂度为O(n),是应用最为广泛的去重方法,而在JavaScript语言中,Hash表是用Object实现的,代码如下。 +``` +function unique(array) { + var newArray = []; + var object = {}; + for (var i = 0; i < array.length; i++){ + if(!object[array[i]]) { + newArray.push(array[i]); + object[array[i]] = 1; + } + } + return newArray; +} +``` +#### Set()方法 +  最新的ES6中新增了Map(),Set()这两种数据结构,以及Array.from()方法,它们底层都是用红黑树实现(一种严格意义上平衡二叉树),它们的操作时间复杂度也就是红黑树的操作时间复杂度都为O(logN)。 +  Set()和Map()的区别在于,Set()中的数据没有重复,这个特性刚好可以用于数组去重,且效率非常高,这么好的数据结构在ES6才被实现,真是可惜。 +  下面看代码,非常简洁: +``` +let arr1 = Array.from(new Set(arr1)); +//NodeJS中已经全面支持ES6,这种方法爽的不要不要的。 +``` +#### 总结 +``` +function newUnique(arr1) { + return Array.from ? Array.from(new Set(arr1)) : unique(arr1); +} +//unique()为上面的Hash方法函数。 +``` \ No newline at end of file diff --git "a/JavaScript\350\257\255\350\250\200\347\262\276\347\262\271[\344\277\256\350\256\242\347\211\210].pdf" "b/JavaScript\350\257\255\350\250\200\347\262\276\347\262\271[\344\277\256\350\256\242\347\211\210].pdf" new file mode 100644 index 0000000..581e410 Binary files /dev/null and "b/JavaScript\350\257\255\350\250\200\347\262\276\347\262\271[\344\277\256\350\256\242\347\211\210].pdf" differ diff --git "a/JavaScript\350\257\255\350\250\200\347\262\276\347\262\271_\344\277\256\350\256\242\347\211\210.pdf" "b/JavaScript\350\257\255\350\250\200\347\262\276\347\262\271_\344\277\256\350\256\242\347\211\210.pdf" new file mode 100644 index 0000000..581e410 Binary files /dev/null and "b/JavaScript\350\257\255\350\250\200\347\262\276\347\262\271_\344\277\256\350\256\242\347\211\210.pdf" differ diff --git "a/JavaScript\351\235\242\345\220\221\345\257\271\350\261\241\347\274\226\347\250\213\346\214\207\345\215\227.pdf" "b/JavaScript\351\235\242\345\220\221\345\257\271\350\261\241\347\274\226\347\250\213\346\214\207\345\215\227.pdf" new file mode 100644 index 0000000..6de62b6 Binary files /dev/null and "b/JavaScript\351\235\242\345\220\221\345\257\271\350\261\241\347\274\226\347\250\213\346\214\207\345\215\227.pdf" differ diff --git "a/JavaScript\351\253\230\347\272\247\347\250\213\345\272\217\350\256\276\350\256\241\357\274\210\347\254\2543\347\211\210\357\274\211.pdf" "b/JavaScript\351\253\230\347\272\247\347\250\213\345\272\217\350\256\276\350\256\241\357\274\210\347\254\2543\347\211\210\357\274\211.pdf" new file mode 100644 index 0000000..a0749a1 Binary files /dev/null and "b/JavaScript\351\253\230\347\272\247\347\250\213\345\272\217\350\256\276\350\256\241\357\274\210\347\254\2543\347\211\210\357\274\211.pdf" differ diff --git "a/Node.js\345\256\236\346\210\230.pdf" "b/Node.js\345\256\236\346\210\230.pdf" new file mode 100644 index 0000000..deb52dd Binary files /dev/null and "b/Node.js\345\256\236\346\210\230.pdf" differ diff --git "a/Node.js\345\274\200\345\217\221\346\214\207\345\215\227_\344\270\255\346\226\207\346\255\243\347\211\210.pdf" "b/Node.js\345\274\200\345\217\221\346\214\207\345\215\227_\344\270\255\346\226\207\346\255\243\347\211\210.pdf" new file mode 100644 index 0000000..a8d206a Binary files /dev/null and "b/Node.js\345\274\200\345\217\221\346\214\207\345\215\227_\344\270\255\346\226\207\346\255\243\347\211\210.pdf" differ diff --git "a/Node\344\270\216Express\345\274\200\345\217\221.pdf" "b/Node\344\270\216Express\345\274\200\345\217\221.pdf" new file mode 100755 index 0000000..e7d5d19 Binary files /dev/null and "b/Node\344\270\216Express\345\274\200\345\217\221.pdf" differ diff --git "a/Node\344\272\244\344\272\222\345\274\217\345\221\275\344\273\244\350\241\214\345\267\245\345\205\267\345\274\200\345\217\221\342\200\224\342\200\224\350\207\252\345\212\250\345\214\226\346\226\207\346\241\243\345\267\245\345\205\267.md" "b/Node\344\272\244\344\272\222\345\274\217\345\221\275\344\273\244\350\241\214\345\267\245\345\205\267\345\274\200\345\217\221\342\200\224\342\200\224\350\207\252\345\212\250\345\214\226\346\226\207\346\241\243\345\267\245\345\205\267.md" new file mode 100644 index 0000000..e4ea11f --- /dev/null +++ "b/Node\344\272\244\344\272\222\345\274\217\345\221\275\344\273\244\350\241\214\345\267\245\345\205\267\345\274\200\345\217\221\342\200\224\342\200\224\350\207\252\345\212\250\345\214\226\346\226\207\346\241\243\345\267\245\345\205\267.md" @@ -0,0 +1,325 @@ +# Node交互式命令行工具开发——自动化文档工具 +  `nodejs`开发命令行工具,流程相对简单,但一套完整的命令行程序开发流程下来,还是需要下点功夫,网上资料大多零散,这篇教程意在整合一下完整的开发流程。 +  [npm](https://www.npmjs.com/)上命令行开发相关包很多,例如`minimist`、`optimist`、`nopt`、`commander.js`、`yargs`等等,使用方法和效果类似。其中用得比较多的是TJ大神的[commander](https://www.npmjs.com/package/commander)和[yargs](https://www.npmjs.com/package/yargs),本文以`commander`为基础讲述,可以参考这篇[教程](http://yijiebuyi.com/blog/2cd3833e8551a302b4ec645031bfd3d0.html),yargs教程可以参考[阮大神的](http://www.ruanyifeng.com/blog/2015/05/command-line-with-node.html)或者[这一篇](https://ideras.me/a-complete-guide-to-yargs/index.html)。 +  另外,一个完整的命令行工具开发,还需要了解`process`、`shelljs`、`path`、`linebyline`等模块,这些都是`node`基础模块或一些简单模块,非常简单,就不多说了,另外如果你不想用回调函数处理异步还需要了解一下`Promise`、`Generator`函数。这是教程:`i5ting`大神的[《深入浅出js(Node.js)异步流程控制》](https://github.com/i5ting/asynchronous-flow-control?utm_source=tuicool&utm_medium=referral)和阮大神的[异步编程教程]( http://es6.ruanyifeng.com/#docs/async)以及[promise小人书](http://liubin.github.io/promises-book/#introduction),另外想尝试ES7 stage3阶段的`async/await`异步解决方案,可参考这篇[教程](http://think2011.net/2015/11/09/ES7-Async-Await/),`async/await`解决方案需要`babel`转码,这是[教程](http://www.ruanyifeng.com/blog/2016/01/babel.html)。本人喜欢`async/await`(哪个`node`开发者不喜欢呢?)但不喜欢倒腾,况且`async/await`本身就是`Promise`的语法糖,所以没选择使用,据江湖消息,`nodejs`将在今年晚些时候(10月份?)支持`async/await`,很是期待。 +  以下是文章末尾实例用到的一些依赖。 + +```json +"dependencies": { + "bluebird": "^3.4.1", + "co": "^4.6.0", + "colors": "^1.1.2", + "commander": "^2.9.0", + "dox": "^0.9.0", + "handlebars": "^4.0.5", + "linebyline": "^1.3.0", + "mkdirp": "^0.5.1" + } +``` +  其中`bluebird`用于`Promise`化,TJ大神的`co`用于执行`Generator`函数,`handlebars`是一种模板,`linebyline`用于分行读取文件,`colors`用于美化输出,`mkdirp`用于创建目录,另外教程中的示例是一款工具,可以自动化生成数据库和`API`接口的`markdown`文档,并通过修改`git hooks`,使项目的每次`commit`都会自动更新文档,借助了TJ大神的`dox`模块。 +  所有推荐教程/教材,仅供参考,自行甄选阅读。 +### 安装Node +  各操作系统下安装见[Nodejs官网](https://nodejs.org/en/),安装完成之后用`node -v`或者`which node`等命令测试安装是否成功。`which`在命令行开发中是一个非常有用的命令,使用`which`命令确保你的系统中不存在名字相同的命令行工具,例如`which commandName`,例如`which testdev`命令返回空白那么说明`testdev`命令名称还没有被使用。 +### 初始化 +1. 新建一个`.js`文件,即是你的命令要执行的主程序入口文件,例如`testdev.js`。在文件第一行加入`#!/usr/bin/env node`指明系统在运行这个文件的时候使用`node`作为解释器,等价于`node testdev.js`命令。 +2. 初始化`package.json`文件,使用`npm init`命令根据提示信息创建,也可以是使用`npm init -y`使用默认设置创建。创建完成之后需要修改`package.json`文件内容加入`"bin": {"testdev": "./testdev.js"}`这条信息用于告诉`npm`你的命令(`testdev`)要执行的脚本文件的路径和名字,这里我们指定`testdev`命令的执行文件为当前目录下的`testdev.js`文件。 +3. 为了方便测试在`testdev.js`文件中加入代码`console.log('hello world');`,这里只是用于测试环境是否搭建成功,更加复杂的程序逻辑和过程需要按照实际情况进行编写 + +### 测试 +  使用`npm link`命令,可以在本地安装刚刚创建的包,然后就可以用`testdev`来运行命令了,如果正常的话在控制台会打印出`hello world` +### commander +  TJ的[commander](https://github.com/tj/commander.js)非常简洁,`README.md`已经把使用方法写的非常清晰。下面是例子中的代码: + +```js +const program = require('commander'), + co = require('co'); + +const appInfo = require('./../package.json'), + asyncFunc = require('./../common/asyncfunc.js'); + +program.allowUnknownOption(); +program.version(appInfo.version); + +program + .command('init') + .description('初始化当前目录doc.json文件') + .action(() => co(asyncFunc.initAction)); + +program + .command('show') + .description('显示配置文件状态') + .action(() => co(asyncFunc.showAction)); + +program + .command('run') + .description('启动程序') + .action(() => co(asyncFunc.runAction)); + +program + .command('modifyhook') + .description('修改项目下的hook文件') + .action(() => co(asyncFunc.modifyhookAction)); + +program + .command('*') + .action((env) => { + console.error('不存在命令 "%s"', env); + }); + +program.on('--help', () => { + console.log(' Examples:'); + console.log(''); + console.log(' $ createDOC --help'); + console.log(' $ createDOC -h'); + console.log(' $ createDOC show'); + console.log(''); +}); + +program.parse(process.argv); +``` +  定义了四个命令和个性化帮助说明。 +### 交互式命令行process +  `commander`只是实现了命令行参数与回复一对一的固定功能,也就是一个命令必然对应一个回复,那如何实现人机交互式的命令行呢,类似`npm init`或者`eslint --init`这样的与用户交互,交互之后根据用户的不同需求反馈不同的结果呢。这里就需要`node`内置的`process`模块。 +  这是我实现的一个`init`命令功能代码: + +```js +exports.initAction = function* () { + try { + var docPath = yield exists(process.cwd() + '/doc.json'); + if (docPath) { + func.initRepl(config.coverInit, arr => { + co(newDoc(arr)); + }) + } else { + func.initRepl(config.newInit, arr => { + co(newDoc(arr)); + }) + } + } catch (err) { + console.warn(err); + } +``` +  首先检查`doc.json`文件是否存在,如果存在执行覆盖交互,如果不存在执行生成交互,`try...catch`捕获错误。 +  交互内容配置如下: + +```js + newInit: + [ + { + title:'initConfirm', + description:'初始化createDOC,生成doc.json.确认?(y/n) ', + defaults: 'y' + }, + { + title:'defaultConfirm', + description:'是否使用默认配置.(y/n) ', + defaults: 'y' + }, + { + title:'showConfig', + description:'是否显示doc.json当前配置?(y/n) ', + defaults: 'y' + } + ], + coverInit:[ + { + title:'modifyConfirm', + description:'doc.json已存在,初始化将覆盖文件.确认?(y/n) ', + defaults: 'y' + }, + { + title:'defaultConfirm', + description:'是否使用默认配置.(y/n) ', + defaults: 'y' + }, + { + title:'showConfig', + description:'是否显示doc.json当前配置?(y/n) ', + defaults: 'y' + } + ], +``` +  人机交互部分代码也就是`initRepl`函数内容如下: + +```js +//初始化命令,人机交互控制 +exports.initRepl = function (init, func) { + var i = 1; + var inputArr = []; + var len = init.length; + process.stdout.write(init[0].description); + process.stdin.resume(); + process.stdin.setEncoding('utf-8'); + process.stdin.on('data', (chunk) => { + chunk = chunk.replace(/[\s\n]/, ''); + if (chunk !== 'y' && chunk !== 'Y' && chunk !== 'n' && chunk !== 'N') { + console.log(config.colors.red('您输入的命令是: ' + chunk)); + console.warn(config.colors.red('请输入正确指令:y/n')); + process.exit(); + } + if ( + (init[i - 1].title === 'modifyConfirm' || init[i - 1].title === 'initConfirm') && + (chunk === 'n' || chunk === 'N') + ) { + process.exit(); + } + var inputJson = { + title: init[i - 1].title, + value: chunk, + }; + inputArr.push(inputJson); + if ((len--) > 1) { + process.stdout.write(init[i++].description) + } else { + process.stdin.pause(); + func(inputArr); + } + }); +} +``` +  人机交互才用向用户提问根据用户不同输入产生不同结果的形式进行,顺序读取提问列表并记录用户输入结果,如果用户输入`n/N`则终止交互,用户输入非法字符(除`y/Y/n/N`以外)提示输入命令错误。 +### 文档自动化 +  文档自动化,其中数据库文档自动化,才用依赖`sequelize`的方法手写(根据需求不同自行编写逻辑),`API`文档才用TJ的[dox](https://github.com/tj/dox)也很简单。由于此处代码与命令行功能相关度不大,请读者自行去示例地址查看代码。 +### 示例地址 +[github地址](https://github.com/threerocks/buildDOC) +[npm地址]( https://www.npmjs.com/package/createDOC) +### 工具说明 +## 简介 + +工具可以自动化生成数据库和API接口的markdown文档,并通过修改git hooks,使项目的每次commit都会自动更新文档。 + +## 安装 + + `npm i createDOC -g` + +## 配置 + - 在项目根目录使用`createDOC init`命令初始化,该命令会在当前目录创建`doc.json`文件。 + - 生成`doc.json`文件后,需要详细配置数据库schemas存储路径(目前只支持关系型数据库),以及路由控制文件,以及子路由目录。 + - API注释规则,遵循TJ大神dox规范,简化版规则如下 + + ```js + /** + * API description + * + * @param {type} name/name=default_value description + * @return {String} description + * @example + * any example + * + * @other description + */ + ``` + +*ps: 此工具为内部使用工具,如个人使用可下载源码,做简单修改即可* +## 使用 + +```sh + Usage: createDOC [options] [command] + + Commands: + + init 初始化当前目录doc.json文件 + show 显示配置文件状态 + run 启动程序 + modifyhook 修改项目下的hook文件 + * + + Options: + + -h, --help output usage information + -V, --version output the version number + + Examples: + + $ createDOC --help + $ createDOC -h + $ createDOC show +``` + +## 示例说明 +doc.json示例 + +```json +{ + "db": { + "schemas": "/Users/mac/Desktop/testssss/schemas", + "markdown": { + "path": "/Users/mac/Desktop/testssss/doc1/", + "file": "db.md" + } + }, + "api": { + "controller": "/Users/mac/Desktop/testssss", + "routes": "/Users/mac/Desktop/testssss", + "markdown": { + "path": "/Users/mac/Desktop/testssss/doc1", + "file": "api.md" + } + } +} +``` +schema.js示例 + +```js +module.exports = function(sequelize, DataTypes) { + return sequelize.define('test_zk_absence', { + //这是id + id: { + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true, + autoIncrement: true + }, + //这是end_data + end_date: { + type: DataTypes.DATE, + allowNull: true + }, + /* + { + a:1, + b:2, + c:{a:2}, + d:'2222' + } + */ + type_id: { + type: DataTypes.INTEGER, + allowNull: true + }, + updated_at: { + type: DataTypes.DATE, + allowNull: false + } + }, { + tableName: 'test_zk_absence' + }); + }; +``` +api注释示例 + +```js +/** + * 获取多个课程 + * @param {Number} examinationId 考试类型 + * @param {Number} subjectId 科目类型 + * @param {Number} statusId=3 状态类型 + * @param {String} startDate 更新开始时间 + * @param {String} endDate 更新结束时间 + * @param {String} keyword 关键词 + * @param {Number} page 页码 + * @return {Array} ok + * @example [1,2,3,3,4] + */ +getCourses(req, params) { + ... ... +} +``` +## TODO +1. 代码逻辑优化,适应力更强。 +2. 代码速度、质量优化。 +3. 加入单元测试 + + + + diff --git "a/Object.create\350\257\246\350\247\243.md" "b/Object.create\350\257\246\350\247\243.md" new file mode 100644 index 0000000..b7e3998 --- /dev/null +++ "b/Object.create\350\257\246\350\247\243.md" @@ -0,0 +1,14 @@ +# Object.create +简单来讲,new Object()是一种通过构造函数来创建object的方式,而Object.create(proto, [ propertiesObject ]) +不需要通过构造函数就可以创建一个object,Object.create()的第一个参数是必须要的,第二个参数可选。其实Object.create()内部依然是通过new一个构造函数的方式来实现的,它有构造函数,不过这个构造函数是隐式存在的,看一下使老旧浏览器支持Object.create方法的“polyfill”就可以对它们之间的区别一目了然了: + +```js +if (!Object.create) { + Object.create = function (o) { + function F() {} //定义了一个隐式的构造函数 + F.prototype = o; + return new F(); //其实还是通过new来实现的 + }; + } + ``` +ps:Object.create可以用于对象的深拷贝,非常好用 diff --git "a/REACT\357\274\232\345\274\225\351\242\206\346\234\252\346\235\245\347\232\204\347\224\250\346\210\267\347\225\214\351\235\242\345\274\200\345\217\221\346\241\206\346\236\266.pdf" "b/REACT\357\274\232\345\274\225\351\242\206\346\234\252\346\235\245\347\232\204\347\224\250\346\210\267\347\225\214\351\235\242\345\274\200\345\217\221\346\241\206\346\236\266.pdf" new file mode 100644 index 0000000..6d82e8a Binary files /dev/null and "b/REACT\357\274\232\345\274\225\351\242\206\346\234\252\346\235\245\347\232\204\347\224\250\346\210\267\347\225\214\351\235\242\345\274\200\345\217\221\346\241\206\346\236\266.pdf" differ diff --git a/README.md b/README.md index cbc3aea..3418405 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,32 @@ -# studyFiles -一些NodeJS和前端的学习笔记,Koa+MongoDB+MySQL+JavaScript+Bootstrap+React+jQuery等等 +# 资源分享 + +一些NodeJS和前端的学习笔记 +一些经典且高质量的电子书 +一些逗比的生活感悟 +一些脑残的成长的经历 + +剧集/电影/电子书等寻找请邮件联系[threerocks](196887298@qq.com) +技术交流请联系[threerocks](196887298@qq.com) + +
+*此目录均为原创文章* + +*转载请注明:* + +*转载自:https://github.com/threerocks* + +
+ GitHub +
+
+ 主页 +
+
+ CNode +
+
+ 简书 +
+ + -*此目录均为原创文章*
-*转载请注明:*
-*转载自:https://github.com/a1511870876*
diff --git "a/css\346\217\255\347\247\230.pdf" "b/css\346\217\255\347\247\230.pdf" new file mode 100644 index 0000000..7f7cd34 Binary files /dev/null and "b/css\346\217\255\347\247\230.pdf" differ diff --git a/javascript-promise-book.pdf b/javascript-promise-book.pdf new file mode 100644 index 0000000..0b75e48 Binary files /dev/null and b/javascript-promise-book.pdf differ diff --git "a/vue\345\255\246\344\271\240\347\254\224\350\256\260.md" "b/vue\345\255\246\344\271\240\347\254\224\350\256\260.md" new file mode 100644 index 0000000..2cfd088 --- /dev/null +++ "b/vue\345\255\246\344\271\240\347\254\224\350\256\260.md" @@ -0,0 +1,4 @@ +## vue学习笔记 +vue不是一个框架,它只是一个提供MVVM风格的双向数据库绑定的库,专注于UI层面。Vue提供的核心是MVVM中的VM,也就是viewModel,它负责连接View和Model。 +vue借鉴了angular和react的经验,使用了angular的双向绑定特性,Angular 的 directive 和 filter的概念,以及react组件化的概念,同时借鉴了两者的API。 +在Vue.js的定义中,View就是用户实际看到的DOM元素,而Model就是原生的JavaScript对象 diff --git "a/\344\270\200\344\270\252\346\234\210\346\202\237\351\200\217JavaScript.pdf" "b/\344\270\200\344\270\252\346\234\210\346\202\237\351\200\217JavaScript.pdf" new file mode 100644 index 0000000..93fd283 Binary files /dev/null and "b/\344\270\200\344\270\252\346\234\210\346\202\237\351\200\217JavaScript.pdf" differ diff --git "a/\344\275\240\344\270\215\347\237\245\351\201\223\347\232\204JavaScript\357\274\210\344\270\212\357\274\211.pdf" "b/\344\275\240\344\270\215\347\237\245\351\201\223\347\232\204JavaScript\357\274\210\344\270\212\357\274\211.pdf" new file mode 100644 index 0000000..052b74b Binary files /dev/null and "b/\344\275\240\344\270\215\347\237\245\351\201\223\347\232\204JavaScript\357\274\210\344\270\212\357\274\211.pdf" differ diff --git "a/\345\233\276\350\247\243HTTP.pdf" "b/\345\233\276\350\247\243HTTP.pdf" new file mode 100644 index 0000000..a298811 Binary files /dev/null and "b/\345\233\276\350\247\243HTTP.pdf" differ diff --git "a/\345\233\276\350\247\243http\351\253\230\346\270\205.zip" "b/\345\233\276\350\247\243http\351\253\230\346\270\205.zip" new file mode 100644 index 0000000..6576967 Binary files /dev/null and "b/\345\233\276\350\247\243http\351\253\230\346\270\205.zip" differ diff --git "a/\346\267\261\345\205\245\345\211\226\346\236\220Koa.md" "b/\346\267\261\345\205\245\345\211\226\346\236\220Koa.md" new file mode 100644 index 0000000..d7c5132 --- /dev/null +++ "b/\346\267\261\345\205\245\345\211\226\346\236\220Koa.md" @@ -0,0 +1,192 @@ +半年前曾经写过一篇[Koa技术分享](https://cnodejs.org/topic/56936889c2289f51658f0926),当时写这篇文章的时候还在校园,实习期间接触一个Koa的项目,之后自己又写了一个[小项目](https://github.com/a1511870876/myblog),之后总结心得便有了上面这篇文章。半年的时间,忙于毕业和论文,git和文章都鲜有更新,如今毕业就业,再次接触Koa,再看这篇文章,感到当时的稚嫩,有很多地方没有考虑仔细,理解也不深入。怀着程序员严谨的精神,准备重写一篇Koa的技术分享。 + +tj的thunkify源码 +``` +/** + * Module dependencies. + */ +var assert = require('assert'); +/** + * Expose `thunkify()`. + */ +module.exports = thunkify; +/** + * Wrap a regular callback `fn` as a thunk. + * + * @param {Function} fn + * @return {Function} + * @api public + */ +function thunkify(fn){ + assert('function' == typeof fn, 'function required'); + return function(){ + //这里就是将所有的参数放进了一个新的数组,这里之所以不用[].slice。是因为有人在bluebird docs发现,如果直接这样泄露arguments,v8的一些优化的编译会被搁置,就会有性能上的损失。 + var args = new Array(arguments.length); + var ctx = this; + for(var i = 0; i < args.length; ++i) { + args[i] = arguments[i]; + } + return function(done){ + //这里用called是为了标记只执行了一次,类似于promise的resolve和reject只能执行一次一样。 + var called; + args.push(function(){ + if (called) return; + called = true; + //因为arguments是一个list,必须得用apply才能在done传入。 + done.apply(null, arguments); + }); + //这里用个try catch,可以在执行失败时走一遍callback,传入err信息 + try { + fn.apply(ctx, args); + } catch (err) { + done(err); + } + } + } +}; +``` +下面的是co源码的逐行阅读,先把参照的一些图片列举出来 +``` +//array原生的slice + var slice = Array.prototype.slice; + //这里写的这么古怪就只是想在es6的模块引入时更加舒服一些,参见下面的图片3 + module.exports = co['default'] = co.co = co; + //将传入的generator函数包装成一个返回promise的方法 + //这是一个独立的方法,就是将传入的函数包装成了co执行前的形式 + co.wrap = function (fn) { + //存了一个指针指向原generator函数 + createPromise.__generatorFunction__ = fn; + return createPromise; + function createPromise() { + //返回的方法调用就会直接执行co。 + return co.call(this, fn.apply(this, arguments)); + } + }; + //执行generator或者generator函数然后返回一个promise + function co(gen) { + var ctx = this; + var args = slice.call(arguments, 1) + // 将所有的东西放到一个promise里面,来防止引起内存泄露错误的promise chaining。 + //tudo:看一下这个issue see https://github.com/tj/co/issues/180 + //参见下面的内存泄露的研究 + //https://github.com/promises-aplus/promises-spec/issues/179 看的我好累,完全没有看懂啊!!! + //总之不管怎样,他是把传进来的东西包装成了一个promise + return new Promise(function(resolve, reject) { + //这里是判断下gen是不是函数,generators function执行之后是一个object + if (typeof gen === 'function') gen = gen.apply(ctx, args); + //传入的不是generators函数,没有next,就直接resolve返回结果;这里是错误兼容而已,因为co就是基于generator的,传入其他的没有意义 + if (!gen || typeof gen.next !== 'function') return resolve(gen); + //主要就是走下面的onFulfilled方法,这个方法返回的是一个promise(resolve或者reject) + onFulfilled(); + function onFulfilled(res) { + var ret; + try { + //调用第一次next方法 + ret = gen.next(res); + } catch (e) { + //出错了直接reject出去 + return reject(e); + } + //将第一次的结果({done:true,value:{}})传入内部方法next + next(ret); + } + //promise失败的时候调用 + //这里在promise错误的时候,就会尝试向外throw err。Genertor的属性,可以内部抛出,外部不活。如果我们对这个yield进行了try catch,就会被捕获,不处理的话,就会reject出去,在co的catch语句中co(*fn).catch处理。 + function onRejected(err) { + var ret; + try { + ret = gen.throw(err); + } catch (e) { + return reject(e); + } + next(ret); + } + //循环得到next的结果,return的还是一个promise + function next(ret) { + //如果done为true的话,代表执行结束,返回一个resolve的promise + if (ret.done) return resolve(ret.value); + //既然还没执行完,就将ret.value转换成一个promise + var value = toPromise.call(ctx, ret.value); + //如果成功转化为了promise,就在这个promise执行完了再调用onFulfilled方法 + if (value && isPromise(value)) return value.then(onFulfilled, onRejected); + return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, ' + + 'but the following object was passed: "' + String(ret.value) + '"')); + } + }); + } + //将yield后面的东西转化成一个promise + function toPromise(obj) { + //如果不存在的话,直接返回,走最后的报错流程 + if (!obj) return obj; + //判断传入的是不是promise,是的话直接返回 + if (isPromise(obj)) return obj; + //判断传入的是不是generator,或者generator function,是的话,继续调用co函数进行循环~ + if (isGeneratorFunction(obj) || isGenerator(obj)) return co.call(this, obj); + //如果就是个普通的thunk函数,也把他转化为promise + if ('function' == typeof obj) return thunkToPromise.call(this, obj); + //如果是array或者object的话,也走相应地变换方法 + if (Array.isArray(obj)) return arrayToPromise.call(this, obj); + if (isObject(obj)) return objectToPromise.call(this, obj); + //如果都不是,直接返回,走最后的报错流程 + return obj; + } + //这里将thunk转化成了promise,thunk就是调用的时候传入一个error和res的function,就在最外面包了个promise就行了 + function thunkToPromise(fn) { + var ctx = this; + return new Promise(function (resolve, reject) { + fn.call(ctx, function (err, res) { + if (err) return reject(err); + if (arguments.length > 2) res = slice.call(arguments, 1); + resolve(res); + }); + }); + } + //这里的array转化为promise其实就是通过Promise.all来包裹,这个方法只接受promise的数组,并且装化为一个新的promise + //参见下面的promise平行执行的研究 + function arrayToPromise(obj) { + return Promise.all(obj.map(toPromise, this)); + } + //将一个object转化为promise,其实就是内部调用了promise.all方法而已 + function objectToPromise(obj){ + var results = new obj.constructor(); + var keys = Object.keys(obj); + var promises = []; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var promise = toPromise.call(this, obj[key]); + if (promise && isPromise(promise)) defer(promise, key); + else results[key] = obj[key]; + } + return Promise.all(promises).then(function () { + return results; + }); + function defer(promise, key) { + // predefine the key in the result + results[key] = undefined; + promises.push(promise.then(function (res) { + results[key] = res; + })); + } + } + //检查是否是promise,果然就是简单的判断他有没有then方法 + function isPromise(obj) { + return 'function' == typeof obj.then; + } + //这里判断是不是generator就是判断他的next和throw方法是不是function + function isGenerator(obj) { + return 'function' == typeof obj.next && 'function' == typeof obj.throw; + } + //判断是否是generatorFunction就是判断了他的constructor的name + function isGeneratorFunction(obj) { + var constructor = obj.constructor; + //这里是为了解决没有constructor的对象,比如Object.create(null) + if (!constructor) return false; + //这里两种情况会返回true,一种是名字正确地,一种是他的prototype是generator + if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true; + return isGenerator(constructor.prototype); + } + //就是通过constructor来判断是不是一个简单的对象 + function isObject(val) { + return Object == val.constructor; + } +``` \ No newline at end of file diff --git "a/\346\267\261\345\205\245\345\211\226\346\236\220let\345\222\214const\345\234\250for\345\276\252\347\216\257\344\270\255\347\232\204\344\275\234\347\224\250\345\216\237\347\220\206.md" "b/\346\267\261\345\205\245\345\211\226\346\236\220let\345\222\214const\345\234\250for\345\276\252\347\216\257\344\270\255\347\232\204\344\275\234\347\224\250\345\216\237\347\220\206.md" new file mode 100644 index 0000000..48e6bb2 --- /dev/null +++ "b/\346\267\261\345\205\245\345\211\226\346\236\220let\345\222\214const\345\234\250for\345\276\252\347\216\257\344\270\255\347\232\204\344\275\234\347\224\250\345\216\237\347\220\206.md" @@ -0,0 +1,53 @@ +# 深入剖析let/const在for循环中的作用原理 +```js +var a=[]; +for(var i = 0;i<3;i++){ + a[i]=function(){console.log(i)} +} +a[1](); //3 +``` +for循环执行过程伪代码如下: + +```js +var a=[] +var i = 0; + +if(i<3) { + a[i]=function(){console.log(i)} +} +i++; + +if(i<3) { + a[i]=function(){console.log(i)} +} +i++; + +if(i<3) { + a[i]=function(){console.log(i)} +} +i++; + +//a ==> [function(){console.log(i), function(){console.log(i), function(){console.log(i)}] + +//a[1] ==> function(){console.log(i) + +a[1](); // console.log(i) ==> 3 因为 i 现在的值是3 + +``` +console.log(i) ==> 3 因为 i 现在的值是3!这句话不对! +console.log(i) ==> 3 因为 i 现在的值是3!这句话不对! +console.log(i) ==> 3 因为 i 现在的值是3!这句话不对! + +而是块级作用域内并没有i,要去上一级作用域局部作用域中找,找到i,局部作用域中分 i现在的值是3。 + +如果把for循环的var换成let呢? + +```js +var a=[]; +for(var i = 0;i<3;i++){ + a[i]=function(){console.log(i)} +} +a[1](); //1 +``` +console.log(i)在其块级作用域内就找到了i,每次for循环把当前i值存入块级作用域。所以a[1]()会打印1; + diff --git "a/\347\262\276\351\200\232JavaScript.pdf" "b/\347\262\276\351\200\232JavaScript.pdf" new file mode 100644 index 0000000..655120b Binary files /dev/null and "b/\347\262\276\351\200\232JavaScript.pdf" differ diff --git "a/\347\274\226\345\206\231\345\217\257\347\273\264\346\212\244\347\232\204JavaScript.pdf" "b/\347\274\226\345\206\231\345\217\257\347\273\264\346\212\244\347\232\204JavaScript.pdf" new file mode 100644 index 0000000..c18ae89 Binary files /dev/null and "b/\347\274\226\345\206\231\345\217\257\347\273\264\346\212\244\347\232\204JavaScript.pdf" differ diff --git "a/\350\213\261\350\257\255\345\215\225\350\257\215.md" "b/\350\213\261\350\257\255\345\215\225\350\257\215.md" new file mode 100644 index 0000000..0123997 --- /dev/null +++ "b/\350\213\261\350\257\255\345\215\225\350\257\215.md" @@ -0,0 +1,181 @@ +
+#### instance +实例 instanceof A instanceof B :检测B.prototype是否存在于参数A的原型链上. +#### type +类型 +#### Iterator +指针对象 +#### Iterable +遍历器 +#### Slice +片 切片 arr.slice(start,end)切片数组 不会改变原始数组,返回一个子数组 +#### splice +拼接 arr.splice(index,num,item1,...,itemN) 方法向/从数组中添加/删除项目,然后返回被删除的项目。该方法会改变原始数组。 +#### split +split() 方法用于把一个字符串分割成字符串数组。 +#### concat +连接 +#### proxy +代理 +#### global +全球/全局 +#### window +不是windows。js默认指向浏览器对象也就是window.name='gloableName'; +#### transfer +合同 +#### fix +固定 +#### parse +解析。JSON.parse(str) 把字符串解析出json对象 +#### stringify +字符串化 JSON.stringify() 从对象中解析出字符串 +#### TODO +待办事项; 备忘录; +#### Model +模型 数据模型 view/controller +#### overflow +清除浮动`.clearfix{ overflow : auto; zoom: 1 }` +#### directive +指示/指令 +#### attribute +属性 Attribute表示属性,指对象(Object)的特征(Feature)翻译成中文术语为“特性” +#### property +属性 翻译成中文术语为“属性” +为了更好的区分attribute和property,基本可以总结为attribute节点都是在HTML代码中可见的,而property只是一个普通的名值对属性。 +``` +// gameid和id都是attribute节点 +// id同时又可以通过property来访问和修改 +
hello
+// areaid仅仅是property +elem.areaid = 900; +``` +#### prototype +原型 每一个基本对象都有自己的_proto_属性,而每一个函数对象都有自己的prototype原型(函数对象也属于基本对象,所以也有_proto_),每当去定义一个prototype的时候,就相当于把该实例的__proto__指向一个结构体,那么这个被指向结构体就称为该实例的原型。 +#### Member Variable +成员变量 +#### Field +字段 +#### method +方法 +#### operator +操作 +#### highlight +高亮 +#### merge +合并 +#### modified +改变 +#### repository [rɪ'pɒzɪt(ə)rɪ] +仓库 +#### detected [dɪ'tektɪd] +发现/发觉 +#### conflicts ['kɑnflɪkts] +冲突 +#### graph [ɡrɑ:f, ɡræf] +曲线/曲线图 +#### branch +分支 git中查看分支:git branch 创建分支:git branch `` 切换分支:git checkout ``合并分支:git merge `` 删除分支:git branch -d `` 创建并切换分支:git checkout -b `` 查看日志曲线:git log --graph +#### sourse +资源 +#### entries +entry的复数 进入/词目 +#### Array +Array.from()把类似数组和Iterable对象转换为数组 Array.of()把多个静态数值转换为数组 +#### arrow +箭头 Arrow function 箭头函数 +#### option +选项 +#### rest +休息/剩余部分/支架 ...rest 得到的是一个真正的数组而不是一个伪数组 +#### apply/call +apply和call都是接受参数改变this指针的指向,arguments,得到的是一个伪数组,且为全部参数。 +#### Calculator ['kælkjuletɚ] +计算器 +#### buffer +缓冲区 +#### sheet +薄片/纸张 +#### duration [du'reʃən] +持续/时长 +#### periods [pɪərɪədz] +周期(period的复数) +#### Uniform Resource Locater ['ju:nifɔ:m],['risɔrs],[ləu'keitə] +统一资源定位符 local本地 location位置 +#### Uniform Resource Identifier [aɪˈdɛntɪˌfaɪ] +统一资源标识符 +关系: +URI 属于 URL 更低层次的抽象,一种字符串文本标准。 +就是说,URI 属于父类,而 URL 属于 URI 的子类。URL 是 URI 的一个子集。 +二者的区别在于,URI 表示请求服务器的路径,定义这么一个资源。而 URL 同时说明要如何访问这个资源(http://)。 +#### origin /ˈɒrɪdʒɪn/ +起源/原点 +#### constants +常量 +#### remote +遥远的远程的 +#### content +内容 +#### count +数量 +#### starter ['stɑ:tə] +发动机/发动者 +#### rhythm /ˈrɪðəm/ +节奏/韵律 +#### orient ['orɪənt] +使适应 +#### resolved +已完成 resolve [rɪ'zɒlv] 解决 +#### rejected +已失败 reject [rɪ'dʒekt] 拒绝 +#### pending +进行中,未决定的,未发生的 pend [pend] 推迟对…的决定;使悬而不决 +#### underway ['ʌndə'weɪ] +adj. 进行中的;起步的;航行中的 +#### fetch [fetʃ] +取来/拿/取得 +#### thunk [θʌŋk] +n. 形实转换程序 +#### params +参数 +#### arguments +参数 +#### thunkify +英语中的"ify"后缀是使……变得……的意思】只是一种普遍的现象,却不是一种普适的语法规则,所以identify( 确定;鉴定;识别)并没有使用这种后缀.(例如 stringify) +#### ident ['aɪdɛnt] +n. 识别,鉴别 +#### preface ['prefəs] +n. 前言;引语 vt. 为…加序言;以…开始 +#### specified [ˈspesɪfaɪd] +adj. 规定的;详细说明的 v. 指定;详细说明(specify的过去分词) +#### configurable +可配置的 config n. 配置 configure vt. 配置/使成型 +#### enum +枚举类型 enumer types枚举类型 enumerable 可枚举的 +#### descriptor [dɪ'skrɪptə] +n. 描述符号 descript vt. 描述 +#### staff [sta:f] +职员 +#### quote [kwəʊt] +vt. 报价;引述;举证 vi. 报价;引用;引证 n. 引用 +#### semicolon ['sɛmɪkolən] +n. 分号 +#### format ['fɔːmæt] +n. 格式;版式;开本 vt. 使格式化;规定…的格式 vi. 设计版式 +#### wrap [ræp] +vt. 包;缠绕;隐藏;掩护 vi. 包起来;缠绕;穿外衣 n. 外套;围巾 +#### emitter [ɪ'mɪtə] +n. 发射器,发射体 +#### utility [juːˈtɪlɪtɪ] +n. 实用;效用;公共设施;功用 adj. 实用的;通用的;有多种用途的 +#### parenthese +括号;圆括号 +#### instance +实例 +#### fulfilled [fʊl'fɪld] +adj. 满足的;十分愉快的 v. 实现(fulfill的过去分词);履行;满足 +#### workflow +工作流 +#### chain +链 +#### token +n. 表征;代币;记号 \ No newline at end of file