yujianAI/segmentfault_upvote5_clean huggingface dataset:
问题：bind,call,apply在实际项目中什么地方会用到 ? 
经常看到介绍call或者apply的文章,然后会以下面这种代码来举例说明 .
```
function identify() {
  console.log("Hello,I'm " + this.name);
}
let me = {
  name: "Kyle"
};
let you = {
  name: "Reader"
};
identify.call(me); // Hello,I'm Kyle
identify.call(you); // Hello,I'm Reader
```
我有点不理解的是,实际开发的时候以参数的形式传给 `indentify(obj)` 方法不是更好吗,
```
// 传参形式
function identify(obj) {
  console.log("Hello,I'm " + obj.name);
}
let me = {
  name: "Kyle"
};
let you = {
  name: "Reader"
};
identify(me); // Hello,I'm Kyle
identify(you); // Hello,I'm Reader
```
那么bind,call,apply一般在实际项目中什么地方会用到 ?

回答：我也同意第二种方法更好。实际上我觉得JavaScript没给`this`一个正式的形参地位就是设计失误，其他函数式/面向对象混合的语言都显式给出了（以至于被Python点名嘲讽，新语言都不敢用`this`这个关键字了），TypeScript如果在`class`之外引用`this`也是要求作为第一个形参显式声明的。编译器知道`this`是隐藏参数，程序员也知道，但大家都闷声大发财，这是最糟糕的。
## 

`bind`可以拿来做偏函数应用，试试往后面继续填参数，这些参数会被“记住”，以便之后使用。
在现代语境下，`call`/`apply`的唯一作用就是把本来是隐藏参数的`this`提成正式参数，允许程序员显式指定。上面举的例子`Math.max.apply(null, [1, 2, 3, 4])`，推荐的做法应该是`Math.max(...[1, 2, 3, 4])`，清晰明了，而且在现代浏览器里性能会略有提升。除非是引用了别人的代码，恕我直言，自愿去搅和`call`/`apply`的，都是文明用语行为。
## 封装起来给别人使用/别人写的代码
个人观察，现在的大趋势也是不做文明用语行为，不在`class`以外乱搞`this`，所以可以期待别人写的代码里需要`call`/`apply`的也会越来越少。koa 1用`this`传上下文被喷了，koa 2马上改成显式形参。lodash这种工具库全是第二种方式传参的，如果想链式调用，都需要手动包装。
vue一大堆`this`，其实一小撮人是有意见的，考虑到一般来说组件的函数都不通用，不存在需要`call`/`apply`的场合，我也就接受了。但vuex的mutations很有可能是通用的，所以也是用的第二种方式传参，要不然真的是超级文明用语。如果是自己写的代码需要别人提供`this`，建议反思一下。
## unbound
上面有回答提到“反柯里化的实现”（实际上我觉得应该叫debound），更多是历史遗留问题的妥协方案。被设计为通用的函数，本身就不应该被绑在特定的类里面，只不过此事已经发生，ES标准又不能大改，只能将就着。像Python这种兼容性喂狗的语言，早就彻底消除了“反柯里化”这种行为的必要性，全是直接用第二种方式传参。不是因为`this`的话，没有必要自找麻烦。
## 总结
- 
`call`/`apply`是历史遗留问题的解决方案
- 
`bind`的用处更广泛些，偏函数应用还是相当好使的
- 为了用那些老库，学习`call`/`apply`还是有必要的
- 自己写的代码不要牵扯`call`/`apply`

标签: 前端, javascript
问题：JAVA为什么要有多个类加载器，1个不行吗

回答：思考以下情景：

1. 首先，是为了区分同名的类：假定存在一个应用服务器，上面部署着许多独立的应用，同时他们拥有许多同名却不同版本的类库。试想，这时候 jvm 该怎么加载这些类同时能尽可能的避免掉类加载时对同名类的差异检测呢？当然是不同的应用都拥有自己独立的类加载器了。
2. 其次，是为了更方便的加强类的能力：类加载器可以在 load class 时对 class 进行重写和覆盖，在此期间就可以对类进行功能性的增强。比如添加面向切面编程时用到的动态代理，以及 debug 等原理。怎么样达到仅修改一个类库而不对其他类库产生影响的效果呢？一个比较方便的模式就是每个类库都可以使用独立的类加载器

小结：
jvm 需要有不同的类加载器，因为它一方面允许你在一个 jvm 里运行不同的应用程序，另一方面方便你独立的对不同类库进行运行时增强。

标签: 类, java, 类加载器, 类加载机制, jvm
问题：npm start 和 npm run start的关系？
npm start 和 npm run start有什么关系吗，
要是在package.json的"scripts"里有 start 项
执行 npm run start 和 npm start 好像是一样的效果
但是如果是别的命令项，
执行 npm run "别的命令" 和npm "别的命令" 效果就会不一样
向大佬求解

回答：`npm start`和 `npm run start`是等效关系，在一个npm管理项目中，一般默认有`start`的定义，且会经常使用，所以就在`npm`执行中简化输入目的设置了`npm run start`的简写，类似的还有`npm stop`、`npm test`等等。而其他的一些不太通用的命令项则只能通过`npm run <命令项>`的形式执行啦。

标签: css, python, html, node.js, javascript
问题：Javascript的生成器函数要多加一个星号，Python却不需要额外标识，为什么这样设计？
一个Javascript的生成器函数是这样的：
```
function *gen(n) {
  for (let i = 0; i < n; i++) {
    yield i;
  }
}
[...gen(10)]
// <- (10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```
Javascript在声明的时候要多加一个星号。如果不加星号，会报`SyntaxError`。
一个python的生成器函数是这样的：
```
def gen(n):
  for i in range(n):
    yield i

>>> list(gen(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```
python在声明的时候不需要额外标识。直接用`yield`就行了。
两个语言都用了`yield`关键词，工作原理也几乎相同，甚至可以说Javascript就是抄的python。那为什么Javascript反而要多加一个星号呢？这个星号有什么意义？为什么要这样设计？是Javascipt太特殊，还是python太特殊？
我相信这应该是有原因的，毕竟ES2015的制定过程相当和谐（字面意义上的）

回答：ES 一直以来在坚持的一个原则便是完全避免 breaking changes，毕竟用户的浏览器版本不是编程人员所能干涉的。如果用户的升级导致某些网站的旧代码失效了，组委会肯定会被喷死。这点和其他语言很不一样。因此 Compatibility 是首要原因，新版 ES 必须完全兼容旧版 ES。
Readability 和 Generality 其实都是产生的附加效果。Generality 其实是个伪需求，空 Generator 都可以被有 0 条或 1 条 yield 语句的 Generator 替代，而且后者可读性比前者更好。Readability 这点 ES 的确实比 Python 的要优秀，至少只阅读函数头我便可以知道这是个 Generator 还是 Normal Function，但优势只有在读长代码时才明显。仅凭这些不足以 diss Python 的设计。
而至于 Python 当年为什么沿用了 `def`，其实没有过多什么“意义”，仅仅是出于 Guido 的直觉而已:-)。

标签: javascript, python
问题：typescript 结合 vue  中  :!  是什么意思
最近在学习结合typescript开发vue，在github中看到这样地问题，一直无法理解
```
  private today!: {
    active: string[] | never[] | number[];
    finishedDate: string[] | never[];
    isReceived: boolean;
  };

  private title?: string;
  private num!: number;
  private isDone!: boolean;
  private isReceived!: boolean;
```
请指点迷津

回答：分开看就好了
`!`是和`?`相对的，是typescript的语法，表示强制解析（也就是告诉typescript编译器，我这里一定有值）。你写`?`的时候再调用，typescript会提示`可能为undefined`
`:`是类型声明

标签: typescript
问题：js 判断一个数是否为正整数？
if ( ( ( number - 0 ) | 0 ) !== number - 0 ){ // 输入购买数量是否为正整数
```
nextBtn.disabled = true;
nextBtn.innerHTML = '请输入正确的购买数量';
return;
```
}
书上看到这样的代码 ( number - 0 ) | 0 ) !== number - 0 
负数 或 0 还不是负数吗？
是不是写错了
如果写错了  按这本书的写法可以怎么写呢？
请大佬帮忙！谢谢了

回答：你这个判断的关键在那个按位或操作符上，如果number是整数的话，比如 10, 那么 `10 | 0 == 10`, 但是 如果是小数的话，或出来的结果也是整数 `10.1 | 0 == 10`。同时有number - 0 操作，那么如果number == 'abc'这样的字符串 `number - 0 == NaN` 这时候再按位与为 `NaN | 0 == 0` 就避免了报错。
回到你的条件，如果number是整数，那么条件不成立，也就不用提示用户再输入正确的数量，如果number是小数，那么条件成立，提示用户输入正确的数量。这个条件不会判断正负，只关心是不是整数。如果number 是 '123'这样的字符串，条件不成立, 如果是 'abc' 这样的字符串，条件成立。
结论： 书上没写错。这个条件会在用户输入小数，非数字的字符串时成立。
如果非要判断>0的话，可以这样写
```
if ((( number - 0 ) | 0 ) !== (number - 0) && (( number - 0 ) | 0 ) <= 0)

```

标签: javascript
问题：js switch奇怪的问题
```
var result_time = 45852221;
var simple_text;

switch (result_time) {

    case result_time < 60:

        simple_text =  '刚刚';

        break;


    case  result_time > 60 && result_time < 3600 : //分钟前

        simple_text = Math.round(result_time/60)+'分钟前';


        break;


    case  result_time > 3600 && result_time < 86400 : //小时前

        simple_text = Math.round(result_time/60/24)+'小时前';

        break;

    case  result_time > 86400 && result_time < 2592000 : //天前

        simple_text = Math.round(result_time/60/60/24)+'天前';


        break;

    case  result_time > 2592000 && result_time < 31104000 : //月前

        simple_text = Math.round(result_time/60/60/24/30)+'月前';


        break;


    case  result_time > 31104000: //年前

        simple_text = Math.round(result_time/60/60/24/30/12)+'年前';


        break;
}
document.write(simple_text)
```
如上图所示，这是一个简化时间的判断语句，为什么它判断不出任何case？

回答：把`switch (result_time)`改为`switch (true)`就行
`switch`的用法：
```
switch (expression)
  case value:
    statement;
    break;
  case value:
    statement;
    break;
```
`expression`和`value`可以是值，也可以是表达式(表达式其实也是值，`1 < 2` 等价于 `true`)，
只要`expression`等于`value`就会执行相关语句
比如:
```
switch (1 < 2)
{
    case true:
        console.log('true');
        break;
    case false :
        console.log('false');
        break;
}
```
```
switch (true)
{
    case 1 < 2:
        console.log('true');
        break;
    case 1 > 2 :
        console.log('false');
        break;
}
```
上面两个代码其实是一样的

标签: javascript
问题：Jsdoc 函数有解构参数时如何注释呢
```
/**
 * 这个函数用来示范一般函数参数注释方式！
 * @param {String} unit
 * @param {Number} item
 */
function foo(name,age) {
    return {name, age}
}

foo("Luke",18)

/**
 * 这个函数的注释写法是什么呢？
 * @param {String} ??? 此时应该如何注释呢
 * @param {Number} ??? 此时应该如何注释呢
 */
function bar({name,age}) {
    return {name, age}
}

bar({
  age: 18
  name: "Luke"
})
```
第二个函数这样写可以不用刻意安排参数的输入顺序，但是如果我想用JsDoc注释时应该怎么写呢？？

回答：```
/**
 * @param {Object} option - foo
 * @param {String} option.name - bar
 * @param {Number} option.age - baz
 */
function bar({name,age}) {
    return {name, age}
}
```

标签: javascript, 注释, jsdoc, jsdoc-3
问题：js中forEach跳出循环问题
去重的时候用for循环是没什么问题的
```
var arr=[2,3,2,2,2,4,5],
            arr2=[];
        function find(arr2,ele){
          for(var i= 0,len=arr2.length;i<len;i++){
              if(arr2[i]==ele) return true;
          }
            return false;
        }

        for(var i= 0,len=arr.length;i<len;i++){
            if(!find(arr2,arr[i])){
                arr2.push(arr[i]);
            }
        }
```
改用forEach的时候
```
 function find(arr2,ele){
            arr2.forEach(function(item,i){
                if(item==ele) return true;
            });
            return false;
        }

        arr.forEach(function(item,i,array){
            if(!find(arr2,arr[i])){
                arr2.push(arr[i]);
            }
        })
```
发现结果不对forEach貌似没有在return的时候跳出循环，求教应该如何写呢。。。。

回答：`forEach`函数不支持`break`，可以用`every`函数替代：
```
function find(arr2, ele) {
  arr2.every(function (item, i) {
    if (item === ele) {
      return false
    }
    return true
  })
}
```
`return false`跳出循环，`return true`继续循环，详见 https://developer.mozilla.org...

标签: javascript
问题：vscode怎么设置打开新文件的时候不关闭没有修改过的旧文件？
经常需要对比两个文件，vscode自动给我关闭了这个有点蛋疼

回答：// 控制是否将打开的编辑器显示为预览。预览编辑器将会重用至其被保留(例如，通过双击或编辑)，且其字体样式将为斜体。
```
"workbench.editor.enablePreview": true,
```
这个设置改为false，就好了

标签: visual-studio-code
问题：Vue刷新当前路由，有什么好的解决方式么？
```
this.$router.go(0);
location.reload() 
//这两种方式都相当于f5刷新，页面会有卡顿的情况
```
```
this.$router.push({ path: '/kong', query: {} });
// 这种方式是进入一个空白页，在空白页里面跳转回原来的页面，这种方式页面刷新相对流畅，
// 但是我发现，使用这种方式的话，在用户点击浏览器的后退键的时候，会再次进入/kong 这个空白页然后马上回来
// 导致页面无法后退
```
请问，有其他好的方式实现页面刷新吗？

回答：如果你希望能从`breforeCreate`开始重走整个生命周期的话
其实在你的这个方法上略作修改就可以
```
this.$router.push({ path: '/kong', query: {} });
```
把`push`换成`replace`
同样的`kong`这个页面里`beforeRouteEnter`时也用`replace`
就不会有那个后退的问题了
附上我用的代码吧
```
// 使用页面
refresh () {
  this.$router.replace({
    path: '/refresh',
    query: {
      t: Date.now()
    }
  })
}

// refresh.vue
<script>
export default {
  beforeRouteEnter(to, from, next) {
    next(vm => {
      vm.$router.replace(from.path)
    })
  }
}
</script>
```

标签: vue.js, javascript
问题：安装好php为什么要复制一份php.ini  到/usr/local/php/lib/php.ini
安装好php为什么要复制一份php.ini  到/usr/local/php/lib/php.ini

我试过了 如果不复制一份 php也能正常运行  为什么要从安装包里复制一份php.ini 到 /usr/local/php/lib/php.ini 目录下呢

回答：对于您的问题，为什么要拷贝到那个目录，那时因为 PHP 编译时指定了配置文件目录，而指定的目录是 /usr/local/php/lib 因此 PHP 启动时会去那个目录下读取 php.ini 的配置文件，不拷贝不影响 PHP 正常运行，只不过无法添加配置项罢了。要查看当前 PHP 会去哪个目录下找配置文件，可以在 phpinfo() 中看到，（命令行下运行 php -i 也可以），看到 'Configuration File (php.ini) Path' 和 'Scan this dir for additional .ini files' 两项，这里面记录了 PHP 加载 .ini 配置文件的路径。
建议下载一份 PHP 的 source code 自己尝试着去编译运行一遍。

标签: php, linux, nginx
问题：npm run dev和npm start的区别？
这是vue脚手架的官方Webpack模版，请问一下其中的"start": "npm run dev"有什么意义
npm run dev和npm start的区别是什么呢？
为什么直接输入npm dev就不能执行scripts配置下的dev命令，而npm start就可以呢？
```
  "scripts": {
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "start": "npm run dev",
    "lint": "eslint --ext .js,.vue src",
    "build": "node build/build.js"
  },
```

回答：执行`scripts`里的命令要`npm run 命令名`。
`npm start`可以运行是为了方便开发者使用，npm-start。
`npm start`会执行`scripts`里的`start`字段。 如果没有`start`字段则执行`node server.js`。

标签: javascript, html5, css, html, node.js
问题：try/catch无法捕获promise.reject的问题
```
function f2() {
  try {
    Promise.reject('出错了');
  } catch(e) {
    console.log(e)
  }
}

```
- 执行`f2()`，无法通过try/catch捕获promise.reject，控制台抛出`Uncaught (in promise)`

```
async function f() {
  try {
    await Promise.reject('出错了')
  } catch(e) {
    console.log(e)
  }
}
```
- 为什么改成await/async后，执行`f()`就能在catch中捕获到错误了，并不会抛出`Uncaught (in promise)`

回答：这样应该就理解了吧，拒绝发生在未来回调只会在未来的事件循环中执行。
```
function f2() {
  try {
    Promise.reject('出错了').catch(err => {
      console.log('2', err)
    });
    console.log('1')
  } catch (e) {
    console.log(e)
  }
}
```

标签: javascript, node.js, ecmascript-6
问题：js数组中对象怎么合并
var list=[{id:1,number:2,title:2},{id:1,number:3,title:2}]
如果数组中id和title的值相同,数组中两个对象合并,number值相加,怎么实现
最终得到[{id:1,number:5,title:2}]

回答：```
var list=[{id:1,number:2,title:2},{id:1,number:3,title:2}]
function merge (list) {
  let result = []
  let cache = {}
  list.forEach(item => {
    let key = `id:${item.id},title${item.title`
    let index = cache[key]
    if (index !== undefined) {
      result[index].number += item.number
    } else {
      result.push(Object.assign({}, item))
      cache[key] = result.length - 1
    }
  })
  return result
}

merge(list)
```

标签: javascript, html5
问题：rpc服务器是不是一般是服务器内部交互用的，这样有什么好处？
最近在学习rpc框架，因为我看有些rpc框架还没跨语言,序列化只有自己语言认识，而那些语言我看很少在客户端开发用到，我这里说的客户端指移动端，浏览器这种。比如golang,python。 那意味着是不是rpc框架主要是用于服务器内网交互的一种架构？ 这样做有什么好处啊？我看貌似好处就是分散流量压力啊，因为用rpc做分布式，计算工作还不全都交到那台server的服务器去做了吗？
我原来还以为rpc架构是客户端软件和服务器交互用的。。。

回答：RPC从概念上讲，不是一种协议，也不属于通信的范畴；
而是一种编程技术，一种代码封装方式，目的是提高代码构建和维护效率。
RPC（Remote Procedure Call）把进程间（包括跨服务器）的通信过程封装成函数调用方式，隐藏复杂的通信处理细节，方便使用、简化代码；使得调用者可以像调用本地函数那样调用其他进程提供的处理过程。
一旦我们把RPC理解为一种代码封装技术，就很容易理解为啥看上去“内网用的多”，“客户端用的少”。
内网并不是关键。
关键是RPC在简化代码的同时增加了耦合。
如果我们定义两个实体之间通过HTTP通信（或其他任何协议），只要双方遵循HTTP协议，就没有问题，和双方的语言实现没有任何关系。
而如果是RPC，那么我们对外部呈现的是函数接口，这就和语言以及平台相关，需要给调用者提供函数声明文件和链接库。
当我们的场景耦合成本比较高时，例如我们构建的服务是提供给团队之外甚至是公司之外的用户使用，用RPC就比直接用HTTP麻烦多了——
我们需要提供各种版本，以支持用户的各种平台和语言。
即使采用支持多语言的RPC框架，那么这个框架（本质是一个代码库）也要双方都引用和依赖，这和直接采用协议比起来耦合要重的多。
显然您所看到的“服务器内网交互用的多“，并不是本质，本质是：
同一个系统内部交互，因为可以采用相同的基础平台（或框架），所以可以考虑使用RPC封装通信过程，以提高代码构建和维护效率，而恰恰系统内部交互大都是走内网。。。

标签: rpc, go, java, python
问题：es6方法过滤掉两个数组中对象id值相等的项
```
const arr1=[{id:1,name:'网'},{id:2,name:'二位'}]
const arr2=[{id:1,name:'老二'},{id:3,name:'老三'}]
```
es6方法过滤掉arr2中id和arr1 id相同的项

回答：我自己来分享个
```
 let arr1=[{id:1,name:'网'},{id:2,name:'二位'}]
 let arr2=[{id:1,name:'问问'},{id:3,name:'多少'},{id:44,name:'多少'},{id:45,name:'多少'},]

  let add=arr2.filter(item=>!arr1.some(ele=>ele.id===item.id))
  console.log(add)
```

标签: javascript, ecmascript-6
问题：go,  python做WEB哪个最合适?
目前处于迷茫状态, 到底该专注一种语言还是同时使用多种语言?
使用golang开发web连续一年了, 频繁的写err!=nil, 频繁的循环断言,reflect,unsafe....感觉大部分时间都在写轮子, 或者考虑轮子的性能. 开发效率来看,是PHP50%吧;  最大的问题的是代码不优雅, 别的语言1行代码, 我用轮子的情况下, 至少要多写两三行.
python,只是看过手册, 很讨厌缩进; 但的确是理想语言, 动态类型更适合快速开发, 库多! 想深入学习, 但又怕go会慢慢淡忘. 
我最开始学c#, 后来用php, c#忘了. 再后来学go, php也几乎忘了. 更别提以前就没学好的C++, 现在连复杂的指针都看不懂了. 但js没忘, 因为几乎天天用啊.
很纠结! 求老鸟指点.

回答：我个人主要是PHP和Golang方向，我谈谈个人的看法吧。
对于开发项目语言技术栈方案的选择，不能仅仅从开发语言本身来进行考虑，还要考虑对应的生态环境，包括软件生态、社区情况和人力资源。
目前整个行业来看的话，PHP拿来做页面级的开发非常适合，也很高效，也就是很多大型互联网公司所谓的“应用层”。Java通过几十年的发展，它的生态环境已经非常繁荣，这也是很多企业选择Java的原因，并且也稳定。Golang相对来说比较新，其实仅仅从开发语言上来讲的话它更加高级(这根设计思想有很大关系)，也是Google踩了几十年的坑产出的结果之一，它并不是为了替代谁，而是给了大家更多的选择。

标签: 编程语言
问题：vue递归组件如何传递事件给父组件？
如题，根据数据遍历递归，不明确具体会遍历几次，形式大概如下：
```
<parent>
    <children>
        <children>
            <children>
                ...
            </children>
        </children>
    </children>
</parent>

```
我现在要在最后一层children传出数据到parent接收，但是emit只能向上传递一层，有什么好的解决方案吗？除了用vuex我没好的想法了

回答：用eventBus 策略。
定义：
```
// bus.js
import Vue from 'vue'
export default new Vue()
```
使用：
parent
```
// parent.vue
import bus from './bus'

export default {
    mounted(){
        bus.$on('post-message',(msg)=>{
            console.log(msg)
        })
    }
}
```
children：
```
// children.vue
import bus from './bus'

export default {
    mounted(){
        bus.$emit('post-message','发送')
    }
}
```

标签: vue.js
问题：为什么JS用分号结尾和没用分号结尾执行的结果不一致？
代码1：
var a = 'Aaa';
var b = 'Bbb';
[a, b] = [b, a];
console.log(a);
console.log(b);
结果：
Bbb
Aaa
代码2：
var a = 'Aaa'
var b = 'Bbb'
[a, b] = [b, a]
console.log(a);
console.log(b);
结果：
Aaa
[ undefined, 'Aaa' ]
如果说JS并不强行要求每行语句末尾必须要用分号结尾的话，上面两段代码按道理来说结果不是应该一致的吗？
测试环境：node　v6.10.2

回答：不强行要求分号不代表不写分号是正确的。解释器会自动加分号，不保证完全能按你的意思加分号也许就加错分号了，结果就错了。变成了
```
var a = 'Aaa';
var b = 'Bbb'[a, b] = [b, a];
console.log(a);
console.log(b);
```

标签: javascript, ecmascript-6
问题：PHP怎么实现数组键名不变，值互换？
```
$arr = array('a'=>'aaa','b'=>'bbb');
转变为
$arr = array('a'=>'bbb','b'=>'aaa');
```

回答：```
$arr = array('a'=>'aaa','b'=>'bbb');
$arr_new = array_combine(array_keys($arr),array_reverse(array_values($arr)));
var_dump($arr_new);
```
=============
哎，迟了一步，@熊猫桑 握爪

标签: php
问题：vim怎么粘贴其他地方复制的代码？
我在网页上复制了一段代码，想粘贴到vim中。
第一次粘贴的时候，总会丢失复制内容的起始几个字符，紧接着第二次粘贴则正常，是什么原因？
下面是`<title>Hello, world!</title>`为粘贴内容的测试结果，共粘贴两次，可以看到，第一次(前面两行)很奇怪，第二次(第三行)正常。
```
  1
  2 , world!</title>
  3 <title>Hello, world!</title>
```
左侧的1 2 3为行号

回答：简单原因: 你没有进入编辑模式就试图编辑文件, 所以产生了你意想不到的结果.
具体原因:
1. 你打开了 vim, 此时 vim 处于 `正常模式`.
2. 你粘贴了 `<title>Hello, world!</title>`, 相当于向 vim 申请执行 该指令, vim 会顺次执行. 在正常模式下, `<` 和 `>` 表示缩进, 但因为你没有选中文本, 因此什么也没有发生, 两个中括号中间的 `title` 是无效的. `Hell` 也不会有具体效果. 但执行到 `o` 时, `o` 表示在光标所在行的下一行进入 `插入模式`, 剩下的内容被当做 插入文本处理. 因此你文件中的第一行是空白行, 第二行是 `o` 后面的内容, 即 `, world!</title>`

3. 因为上面的操作已经使 vim 进入 `插入模式`, 且你并未点击 `ESC` 退出该模式, 因此在你继续进行第二次粘贴的时候, 就会直接执行插入操作, 这行被完整的插入进去了。

疑问:
如果两次粘贴中间没有其他操作, 那么第二次粘贴时不应该会另起一行. 我猜测你应该敲了一个回车符后进行的粘贴.
建议:
了解下 vi 操作基础.

标签: vim, linux
问题：关于前后端分离数据接口的问题？
公司有一个小项目自己采用了前后端分离的方式，就是我在js中采用ajax请求后端提供的数据接口（主要是一些文字内容）。有的同事对这种做法提出了自己的疑问，就是数据接口都是写在js中的，那么上线后就有可能被其他人通过查看js的数据接口地址恶意破坏，比如多次循环访问这个接口，造成服务器负荷比较大。
疑问：前后端分离会造成诸如以上的安全问题吗？如何有效避免呢？

回答：你那个同事水平有限，不要跟他做朋友。
ajax请求也可以加各种权限校验啊。如果能破解了校验，那就算通过页面返回数据，不是一样能模拟发页面请求么？
再说，多次调接口对服务器有压力，那多次请求页面不也有压力么？

标签: javascript, html5, ajax, 前后端分离, 前端
问题：前端进行兼容性测试的标准流程是什么？
现在业界是怎么进行兼容性测试的？不仅包括IE低版本，还有Chrome、Firefox等的低版本，还是说现在默认不测现代浏览器低版本的兼容性了？那这个低版本有没有一个具体的分界点？

回答：看项目需求吧，一般看项目的兼容性需求；
- 一般来说，PC端兼容性测试指IE的兼容性，Chrome、Firefox的兼容性一般来说很少人测，基本上IE的兼容性测试通过了就OK；
- IE兼容性又大概分两个阶段，IE10和IE8；目前一般甚少需要兼容到IE8或以下的了（除非是政府项目，有些还需要兼容到IE6），所以如果项目不特别说明兼容性，一般兼容到IE10就可以了。
- 兼容性测试没有什么标准流程，一般来说都是测试人员手动测试的（听说目前有云测，不过了解了下基本是针对APP的）
- 至于测试平台，可以安装浏览器插件进行基本测试，不过兼容性没有真机测试准确，会有偏差；严格点的测试应该在真机或者虚拟机上测试。

标签: javascript, 前端, 兼容性
问题：为什么Webpack生成JavaScript代码要引入eval模式
最近在看Webpack的生成的JavaScript，有一个疑问想不明白：为什么Webpack要提供`eval`的模式，将模块的generated code用`eval`来包裹？
这里的讨论不仅限于`devtool`是`eval`，还包括`eval-source-map`, `cheap-eval-source-map`等各种包含了`eval`的衍生组合。如果说`eval`的好处是build速度快，因为它不生成source map，那类似于`eval-source-map`这样的呢？
所以我的疑问并不在于source map，而是`eval`本身。既然它如此被诟病，为什么Webpack还是要引入这样一种代码生成机制，它究竟有什么好处？

回答：goto也被诟病，但你仍然可以在C/C++中使用goto。
真正被诟病的不是eval，而且eval的滥用。如果你确认拿到的代码是你自己的（或任何你信任的），用eval是完全可以接受的，而且可以享受到速度快的好处。

标签: javascript, webpack, 前端, eval
问题：css如何让某个元素不继承父元素的宽度，而让子元素撑开他？
这里这个例子：
https://jsfiddle.net/93bh7vpz/
如何让inner这一层和里面所有层的宽度都等于最最最里面的

回答：html元素宽度不具有继承特性，块级元素(block)的宽度会占据一整行，所以看似继承了，实则不是。
让一个元素的宽度根据内容撑开，只要设置其display不为块级元素，不设置宽度就可以了
比如float,inline,position为absolute,fixed等等等等(真的很多，不是块元素，不要设置宽度)

标签: css
问题：Js怎么做这题目，
4444
 333
  22
   1
  22
 333
4444
用JS怎么做。我只会做1以上那半求大神
4444
 333
  22
   1
  22
 333
4444
我只会做1上面那半

回答：```
function f(n) {
  for (let i = -n; i <= n; i++) {
    if (i === 0 || i === 1) {
      continue
    }
    let k = Math.abs(i)
    console.log(k.toString().repeat(k))
  }
}
```

标签: javascript, javascript专题系列
问题：将一个对象填入window.localStorage后访问不到其中的属性？
```
window.localStorage.setItem('obj', {name: 'hhh', age: 100});


```
localStorage.obj 是存在的，但 localStorage.obj.name 是undefined.
请问如何访问到name的value？

回答：`localStorage注意事项`
一般我们会将JSON存入localStorage中，但是在localStorage会自动将localStorage转换成为字符串形式
这个时候我们可以使用JSON.stringify()这个方法，来将JSON转换成为JSON字符串
示例：
```
if(!window.localStorage){
    alert("浏览器不支持localstorage");
}else{
    var storage=window.localStorage;
    var data={
        name:'luozz',
        sex:'man',
        hobby:'program'
    };
    var d=JSON.stringify(data);
    storage.setItem("data",d);
    console.log(storage.data);
}
 
```
读取之后要将JSON字符串转换成为JSON对象，使用JSON.parse()方法
```
var storage=window.localStorage;
var data={
    name:'luozz',
    sex:'man',
    hobby:'program'
};
var d=JSON.stringify(data);
storage.setItem("data",d);
//将JSON字符串转换成为JSON对象输出
var json=storage.getItem("data");
var jsonObj=JSON.parse(json);
console.log(typeof jsonObj);
```
另外还有一点要注意的是，其他类型读取出来也要进行转换

标签: html5, localstorage
问题：如何在学习在工作中用不到的技术？
在工作中一些技术并没有实践机会，比如一些公司项目并没有用到vue、webpack等等，在这种情况下如何去学习用不上的技术？

回答：这个问题我应该很有发言权
1 首先找个早八晚五的公司，不要相信996能提高技术，提高的只是1+1=2这种问题的熟练度，而且你回家以后很累并不能坚持学习
2 满足1的前提下，学自己想学的知识。强迫自己回家之后写代码，不需要太多一百多行就行

标签: 程序员
问题：前后端分离koa2的作用是什么？
如前后端分离项目 vue + axios + koa2 + java（springboot） 使用restful风格api
问题：
1. koa2到底扮演什么角色？具体点就是什么代码应该写在koa2中呢？
2. vue+koa2 前端组合下，路由应该写在哪里呢？vue-router？ koa？ koa-router？，如果vue和koa2中写两次路由意义在哪里？
3. 有人说的一个场景，后台一般不会把数据根据前端展示字段包装，而是一坨扔过来，然后用koa2进行拆解整合，在给vue显示，这算koa2存在的一个理由么？
4. 用 vue-cli 生成一个项目， 其实就都可以实现前端要求了包括node服务器、webpack等，那么极端点说：在加上axios就都可以啦，koa2没用啊......

回答：1.你用vue-cli生成的项目里的koa只是在开发环境里有用，模拟server，在生产环境里是不需要koa的
2.一般的前后端分离的项目也很少需要在前端后后端java之间加一层node，也就是koa，除非是像淘宝这种，需要首屏优化或者有强烈的seo需求的，需要浏览器请求到的就是可以直接展示的静态页面的，或者是后端java提供的api不能直接给前端展示的，需要经过转换的，才会需要node中间层
3.vue-router是前端路由，是在浏览器里执行的，url改变，切换不同的页面，而 koa-router主要是针对服务端的，对于api的路由

标签: 前后端分离, koa2, vue.js
问题：webpack4，不再支持extract-text-webpack-plugin
今天体验了一下webpack4.1.0，发现不再支持 extract-text-webpack-plugin。
那应该用什么方法去单独提取css文件呢？
还有一个问题是，我在看别人用webpack打包的一个开源项目的时候，发现它的html中，是这样引入css的
```
<link type="text/css" rel="stylesheet" href="blob:null/e83446f1-423b-40a8-a91a-d885bde94722">
```
那个 href 中的内容是什么意思啊，是用什么插件完成的？
而且我在文件内也没找到它生成的css文件，只有源码中的scss文件。
实在的搜索不到答案。请大神指教一下，先谢过了。

回答：原因：`extract-text-webpack-plugin` 最新版本为 `3.0.2`，这个版本还没有适应 `webpack 4` 的版本
解决办法：使用 `4.0 beta` 版，`npm install --save-dev extract-text-webpack-plugin@next`

标签: webpack
问题：关于token不理解的地方
目前在写api接口，是为移动端提供的接口，那么我们为用户设定了用户名密码的同时，为何还要加一个token？而且文档还说以token的方式来验证？那每次直接确认用户的密码不行吗？这个token作用是啥？百度说的不清楚啊

回答：例如：
云冲印应用要访问你的百度网盘，读取网盘图片然后打印给你。但是它需要你的账号和密码才能登录访问你的网盘。你会放心把账号密码给它用吗？但是你可以授权网盘给云冲印一个令牌，这个令牌有效期10天。云冲印有了这个token，就相当于有了你的账号和密码。就可以拿着token去访问你的网盘数据了。这样你的密码不会泄露。你可以随时取消这个授权，这样可以禁止别人去读取你的数据。如果你给了账号和密码，那么以后想取消授权就只能改密码了。
用户密码存储在本地是不安全了，别人有机会可以看到你的明文密码。API是无状态的，难道每次请求都要把用户名和密码带上吗，这样会不安全。
本质上 token = 用户名 + 密码

标签: python, django, java, c
问题：node中跨域代理 proxyTable的原理是什么？
1.node中跨域代理 proxyTable的原理是什么？
2.我在浏览器和服务端都没有设置CORS的情况下，只要设置proxytable就可以跨域了，这样是不是就违背了同源策略的初衷？
ps: 希望见到比较有水准的解释

回答：跨域是浏览器禁止的，服务端并不禁止跨域 
所以浏览器可以发给自己的服务端然后，由自己的服务端再转发给要跨域的服务端，做一层代理
`vue-cli`的`proxyTable`用的是`http-proxy-middleware`中间件
`create-react-app`用的是`webpack-dev-server`内部也是用的`http-proxy-middleware`
`http-proxy-middleware`内部用的`http-proxy`

标签: node.js, vue.js, 跨域
问题：关于promise中reject和catch的问题
reject和catch是否都会执行，或者只执行其中一个，分别在什么情况下执行？

回答：### 一、reject后的东西，一定会进入then中的第二个回调，如果then中没有写第二个回调，则进入catch
```

 var p1=new Promise((resolve,rej) => {
    console.log('没有resolve')
    //throw new Error('手动返回错误')
    rej('失败了')

 })

 p1.then(data =>{
    console.log('data::',data);
 },err=> {
    console.log('err::',err)
 }).catch(
    res => {
    console.log('catch data::', res)
 })

 VM367054:2 没有resolve
 VM367054:11 err:: 失败了

```
- then中没有第二个回调的情况

```

 var p1=new Promise((resolve,rej) => {
    console.log('没有resolve')
    //throw new Error('手动返回错误')
    rej('失败了')

 })

 p1.then(data =>{
    console.log('data::',data);
 }).catch(
    res => {
    console.log('catch data::', res)
 })

 VM367054:2 没有resolve
 VM367054:11 catch data:: 失败了

```
- 如果没有then， 也可以直接进入catch

```
 var p1=new Promise((resolve,rej) => {
    console.log('没有 resolve')
    //throw new Error('手动返回错误')
    rej('失败了')

 })

 p1.catch(
    res => {
    console.log('catch data::', res)
 })
VM367087:2 没有resolve
VM367087:9 catch data:: 失败了

```
### 二、resolve的东西，一定会进入then的第一个回调，肯定不会进入catch
```
 var p1=new Promise((resolve,rej) => {
    console.log('resolve')
    //throw new Error('手动返回错误')
    resolve('成功了')

 })

 p1.then(data =>{
    console.log('data::',data);
 }).catch(
    res => {
    console.log('catch data::', res)
 })
VM367087:2 resolve
VM367087:9 data:: 成功了

```
- 不会进入catch的情况

```
 var p1=new Promise((resolve,rej) => {
    console.log('resolve')
    //throw new Error('手动返回错误')
    resolve('成功了')

 })

 p1.catch(
    res => {
    console.log('catch data::', res)
 })
VM367087:2 resolve

```
 throw new Error 的情况和rej一样，但是他俩只会有一个发生 
 另外，网络异常（比如断网），会直接进入catch而不会进入then的第二个回调 

标签: javascript, 回调
问题：Js在数组中添加元素
如何提取数组中的字段，然后添加新的字段，获取数据如下：
```
var data = [
{"id":"1","name":"华为","data":"25u6s8f545d3"},
{"id":"2","name":"小米","data":"cd58de9d3c5d"},
];
```
我想获得的数据格式如下：
```
var data = [
{"id":"1","name":"华为","data":"25u6s8f545d3","mac":"25:u6:s8:f5:45:d3"},
{"id":"2","name":"小米","data":"cd58de9d3c5d","mac":"cd:58:de:9d:3c:5d"},
];
```
我现在方法如下：
```
for (var i = 0; i < data.length; i++) {
    var mac = data[i].data.toUpperCase();
        mac1 = mac.substring(0, 2);
        mac2 = mac.substring(2, 4);
        mac3 = mac.substring(4, 6);
        mac4 = mac.substring(6, 8);
        mac5 = mac.substring(8, 10);
        mac6 = mac.substring(10, 12);
        var mac = mac1 + ':' + mac2 + ':' + mac3 + ':' + mac4 + ':' + mac5 + ':' + mac6;
        data[i].mac = mac;
 };
```
请教下有没有更好的方法？我觉得自己方法有点烂。

回答：```
var data = [
  { "id": "1", "name": "华为", "data": "25u6s8f545d3" },
  { "id": "2", "name": "小米", "data": "cd58de9d3c5d" },
];
data.forEach(item => {
  item.mac = item.data.replace(/\w{2}\B/g, '$&:')
})
console.log(data)
```

标签: javascript
问题：web框架中的controller、service层、dao层、logic层的联系与作用啊
### 一直不太理解controller、service层、dao层、logic层这几个概念，以及具体如何用、为何这样用

回答：说下个人目前在用的分布
Controller:接受Web请求,分发调用不同的逻辑或服务完成一项事情,返回数据
  service:做些服务Api接口相关的代码
   dao:和数据库打交道(对表进行增删改查)
   logic:自己的业务逻辑相关
```
现在有个PC注册账号的功能
  1:初始阶段,controller收到请求,直接在controler里面写数据库连接，进行增删改查,没毛病，可以运行。
  2:慢慢发展,功能多了，Controller多起来了，contoller到处都是sql和数据库打交道的代码,虽然不影响运行,但是有时候发现,如果我要修改一个数据表的字段或其他东西,得到好几个Controller里面去找相同的一个代码并修改,太麻烦了,干脆都放到一个里面,全部对增删改查从同一个地方多好,这时候出现了dao层。
  3:继续发展,进军移动端,有了手机注册的功能，简单,写呗，写着写着发现,我去，怎么和PC注册功能这么像？都要校验用户信息->判断数据库有无重复->插入数据库（重复的业务功能在几个控制器都要被重复使用），有了第二步的经验,把这些相同的业务操作抽离放到一起呗，出现了logic层(logic层负责做些处理并调用dao层完成数据的入库等和数据库打交道的事情),RegisterLogic，规定所有的注册功能都走这一个逻辑了,维护更加方便了,以后即使增加一百种注册方式,只要 new RegisterLogic()->register();就行了。
  4:继续发展下去,公司有声有色的,老板说，网站太无聊了，加点天气预报,随机推送笑话的附属功能吧,这行功能不属于自己的系统的业务逻辑,更具第二步和第三步的经验，应该单独放一个地方,没准以后其他的地方会用到,这时候service层就出现了。
  
```

标签: php, java
问题：jwt前端加密后端解密
最近在学习jwt，但是遇到一个问题。
用户输入用户名和密码之后发送给服务器，服务器将其加密后返回token，每次前端请求都带上这个token。
于是我产生一个问题：用户输入账号和密码如果这个请求被拦截了就能拿到了账号密码，但是有一种叫openssl的东西，就是要求域名用https。但是这种方式也不是十分安全。
既然jwt有JavaScript版，那为啥不在前端就加密了，之后后端解密去验证呢？
问题：jwt前端加密账号密码，后端解密如何实现？
现在做的项目也有token的做法，实现方式：
1.页面加载前端发送一个16位后端就会返回一个publick_key。
2.前端收到这个public_key将用户名密码还有一个16位的随机数用md5加密。
3.登陆的时候将上面的加密发送给后端，后端使用private_key解密后得到加密的数据。
我想上面的实现方式就跟jwt类似。

回答：先不管JWT和SESSION机制，我来讨论下网络安全问题，可能说的不对，欢迎指正。
假定现在你的电脑不安全，电脑中被安装了木马监听，同时网关里有也中间人：
1. 无论你的网页中是否加密，你在键盘中输入的任何数据都会被木马监听到，这是操作系统层的监听；
2. 你在网页中键入的请求以及接收到的响应，通过网关都会被中间人拦截，这是路由层的监听；

所以，加密密码必须采用哈希算法，而不是对称加密；不然中间人既然可以拦截所有的请求和响应，而js又是明文，你如何保证对称加密的秘钥不被中间人看到呢？
> 你可能会问加密的密码也会被看到，中间人也可以绕开网页，直接发包模拟请求。是的，确实如此；加密密码解决的是不让你的密码被明文泄露，这样中间人无法用你的账户密码去其他应用中撞库。

但是传输的主体内容是不能采用哈希算法，因为双方必须知道具体的内容，这导致了中间人会看到明文的内容；(简单的JS对称加密是无用的，因为HTML是明文的，中间人也可以看到对称加密的秘钥)
HTTPS解决的就是对称加密的问题，将证书提前准备好，并通过浏览器预先安装的根证书来避免中间人伪造证书，这从根本上解决对称加密的秘钥问题。
而JWT我觉得从根本上，并不是为了解决网页安全问题，而是想通过一种分布式无状态的方式来解决服务端的SESSION问题。

标签: javascript, html5, php
问题：mongoose 的Virtual是什么？
Virtual properties are document properties that you can get and set but that do not get persisted to MongoDB. 
这句话看不是很懂。请不要翻译，希望能用自己的话解释，有例子更好。谢谢

回答：大致意思就是，你可以用mongoose添加和设置虚拟属性，但是这虚拟属性的值不会保存到数据库中。
比如，前台传到后台一个参数name，代表用户的名称，但是数据库保存的是两个字段，姓和名，这就可以用虚拟属性
```
// 数据库中缓存的格式
var schema = new Schema({
    name: {
        first: { 'type': String },  
        last: { 'type': String },
      }
});

// 当获取该 schema 的fullname属性时,将 schema 中的 name.first 和 name.last 拼接起来返回
var virtual = schema.virtual('fullname');
virtual.get(function () {
  return this.name.first + ' ' + this.name.last;
});
// 当设置该schema的 fullname 属性时,将设置的字以空格分开,分别赋值给 schema 中的 name.first 和 name.last 属性
var virtual = schema.virtual('fullname');
virtual.set(function (v) {
  var parts = v.split(' ');
  this.name.first = parts[0];
  this.name.last = parts[1];
});

// 将该 schema 保存到数据库中时,只会保存 name.first 和 name.last
// fullname属性的值不会保存到数据库中,这就是virtual

```
http://mongoosejs.com/docs/ap...
set 中的 function 的参数 v,是设置虚拟属性时的值.不保存到数据库中,但是它也是有存在的意义的,比如,就像例子中的,在用户看来,它只有一个名字,但是在数据库中,是要保存姓和名,因为分为姓和名,我们后续可以对用户做统计,姓张的多少人.(这也只是举个例子).
再比如,订单的状态,数据库中保存的是0,1,2,3,4,5,6,7.但是在页面上,显示的是未支付,已付款,待发货,已发货,待收货,已完成,待评价等.我们就可以设置一个虚拟属性
```
var virtual = schema.virtual('statusName');
virtual.get(function () {
  switch(this.status){
     case 0: return '待发货';
     case 1: return '待收获';
     case 2: return '已完成';
     default: return '待支付';
  }
  return this.name.first + ' ' + this.name.last;
});
```

标签: mongoose, mongodb
问题：angular4项目中使用ng server启动 别人在局域网里访问无效
angular4项目中使用ng server启动后本地用localhost:4200可以打开，在局域网里别人用我的局域网地址无法访问我的项目

回答：运行ng serve --host xxx.xxx.x.xxx（自己的ip地址）,然后别就可以通过你的ip地址访问了。
好像在项目里面也可以配置的，配置了的话可以直接运行ng serve就行，具体怎么弄我也忘了

标签: server, angular4, 局域网
问题：前端面试时被问到JS异步执行的问题：有A、B、C三个任务，要求：A和B异步执行，二者都完成后执行C
前端面试时被问到JS异步执行的问题：有A、B、C三个任务，要求：A和B异步执行，二者都完成后执行C

回答：方案一，`Promise.all`形式：
```
var promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log(1);
        resolve()
    }, 0);
    
});
var promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log(2);
        resolve()
    }, 0);
});
Promise.all([promise1, promise2]).then(function(res) {
  console.log(3)
});
```
方案二，`callback`形式：
```
var index = 0

function C(){
    console.log(3);
}

setTimeout(() => {
    console.log(1);
    index++;
    if(index === 2){
        C()
    }
}, 0);

setTimeout(() => {
    console.log(2);
    index++;
    if(index === 2){
        C()
    }
}, 0);
```

标签: javascript, 异步
问题：数组中对象去重的方法
如下一个数组，怎么去除其中的重复对象，求大神给个方法，谢谢啊
```
arr = [
{orgId:"100",orgName:"信息组"},
{orgId:"100",orgName:"信息组"},
{orgId:"100",orgName:"信息组"},
{orgId:"81",orgName:"安全组"},
{orgId:"11",orgName:"秘书组"},
{orgId:"81",orgName:"安全组"}
]
```

回答：```
var arr = [
  { orgId: '100', orgName: '信息组' },
  { orgId: '100', orgName: '信息组' },
  { orgId: '100', orgName: '信息组' },
  { orgId: '81', orgName: '安全组' },
  { orgId: '11', orgName: '秘书组' },
  { orgId: '81', orgName: '安全组' },
];

Object.values(
  arr.reduce((obj, next) => {
    var key = JSON.stringify(next);
    return (obj[key] = next), obj;
  }, {}),
);

```
我来个最简单的，but 有个缺点，arr里面的对象必须能被 JSON.stringify 处理

标签: javascript
问题：python二维列表，每个子列表（元素个数不同）取一个元素进行组合，列出所有可能的情况
比如，已知二维列表[[a,b,c],[d,e],[f]],要求从每个子列表中选出一个元素进行相加，列出所有的组合情况，本题输出为adf,aef,bdf,bef,cdf,cef这6种可能。有很多这样的列表，子列表个数不一定相同，请教怎么用python进行处理

回答：```
>>> import itertools
>>> s = [['a','b','c'],['d','e'],['f']]
>>> [''.join(i) for i in itertools.product(*s)]
['adf', 'aef', 'bdf', 'bef', 'cdf', 'cef']
```

标签: python
问题：看一个题，谁能帮忙解释一下？这是一个关于reduce递归
看以下题目：
```
var f = (function() {
    let r = 1;
    return function(...args){
        r *= args.reduce((p, n) => p + n);
        f.valueOf = () => r;    // 主要是这句代码，完全懵B
        return f;
    }
}());
+f(1,2,3)(2,3)(3,4,5)(6,7)
// 输出值为(1+2+3)*(2+3)*(3+4+5)*(6+7)的计算结果
```
考虑到用到的知识点

1. reduce
2. valueOf
3. 递归
4. ...（涉及的没提到的）

回答：1  `reduce` 配合 `args` 解构用来求每一个圆括号里面的和
```
const sum = (...args) => args.reduce((i, j) => i + j)
```
2  每次圆括号执行`f`都会再返回这个`f`，保证了这个`f`后面可以跟上无限多个圆括号
```
var j = (function() {
  return function () {
    console.log('yo')
    return j
  }
}())

j()()()() // yo yo yo yo
```
3  立即执行函数保证了每有一个圆括号都立即、顺序执行
```
var f = function() {
    let r = 1
    return function f(...args){
        r *= args.reduce((p, n) => p + n)
        console.log(args) // 第一个圆括号就不执行了
        f.valueOf = () => r
        return f
    }
}
```
4  如果你只想得到返回的 `f` 函数，或者是只想让这个 `r` 存在于各个层级 `f` 的上下文中的话，`valueOf` 都没有出现的意义，但是如果你想从 `f()()()` 中把 `r` 取出来，就需要 `valueOf` 了。最后的加号会用到他，这里就返回当前上下文中的 `r`。
```
var f = (function() {
    let r = 1
    return function f(...args){
        r *= args.reduce((p, n) => p + n)
        if (args.length == 2) return r // 如果你能找另外一个方式把 r 输出也是可以的
        return f
    }
}())
console.log(f(1,2,3)(2,3,5)(3,4,5)(6,7))
```

标签: javascript
问题：下载了别人的github上的代码，然后创建自己的分支如何把自己的代码贡献给他？

回答：1. 在对方仓库的首页上点 fork，分叉一份到自己名下
2. 创建分支，分支名尽量清晰，尊重对方的规范，比如 `bugfix-some-thing-should-be-right`

3. 开发，测试，编写测试用例，写清楚文档
4. 推到自己的仓库
5. 在这个分支上，会看到一个“Create Pull Request”的按钮，按下创建 PR
6. 对方会审查你的 PR，如果的确有用，他就会合并

整个过程，都需要遵守对方的要求，比如代码规范、分支 PR 的命名规范、文档、测试用例的规范等。

祝你做个好的 contributor。

标签: javascript
问题：一道js的数组算法题
有一个数组:
```
const arr = [[1,2],3,[4,5,6]];
```
定义一个函数，传入arr后，返回值为一个二维数组：
```
[[1,3,4],[2,3,4],[1,3,5],[2,3,5],[1,3,6],[2,3,6]]
```

回答：```
function f(arr) {
  var ret = []

  function fi(result, i) {
    if (i === -1) {
      ret.push(result)
    } else {
      let items = arr[i]
      if (!Array.isArray(items)) {
        items = [items]
      }
      items.forEach(item => {
        fi([item,...result], i - 1)
      });
    }
  }
  fi([], arr.length - 1)
  return ret
}
const arr = [[1,2],3,[4,5,6]];
console.log(f(arr))
```

标签: java, node.js, html5, javascript
问题：路径中`@/`代表什么意思，与`./`有何区别呢？
我在一个项目代码中看到：
```
import store from '@/vuex/store'

```
请问它与：
```
import store from './vuex/store'

```
有什么区别？

回答：`import store from './vuex/store'`是相对路径，代表当前路径同级下vuex下的store
`import store from '@/vuex/store'`也是相对路径，和上面意思差不多，但是具体代表什么路径，要看你webpack里面对于`@`是如何配置的，比如我的:
```
alias: {
  'vue$': 'vue/dist/vue.esm.js',
  '@': resolve('src'),
  'Axios': 'axios' 
}
```

标签: vue.js, ecmascript-6
问题：vue 项目，ios上audio音频 无法自动播放
spa页面，初次进入音乐播放界面的时候，在ios上无法自动播放，通过play()方法还是无法实现播放。有什么方法可以解决的

回答：我是这样做的：
```
//--创建页面监听，页面加载完毕--触发音频播放
document.addEventListener('DOMContentLoaded', function () {
    function audioAutoPlay() {
        var musicEle0 = document.getElementById('music_mp3_0');
        musicEle0.play();
    }
    audioAutoPlay();
});
//--创建触摸监听，当浏览器打开页面时，触摸屏幕触发事件，进行音频播放
document.addEventListener('touchstart', function () {
    function audioAutoPlay() {
        var musicEle0 = document.getElementById('music_mp3_0');
            musicEle0.play();
    }
    audioAutoPlay();
});
```

标签: javascript, vue.js, html5
问题：分享一道面试题，请指点结果为何是undefined
```
if(!("a" in window)){
    var a = 10;
}
console.log(a); // undefined


```

回答：```
因为变量提升到作用域顶部

//变量提升
var a ;

//此时 a 为全局变量  a in window 为 true

if(!("a" in window)){
 var a = 10;
}
console.log(a); // undefined
```

标签: javascript
问题：redux中间件对于异步action的意义是什么？
不太理解类似于redux-thunk这样的中间件对于发送异步action有什么意义，
不可以在异步回调之后直接手动dispatch一个action吗？

回答：首先，我不知道你入和对意义的定义？性能变好？代码可读性增加？扩展性变强？
If you’re not sure whether you need it, you probably don’t.
如果你处于这个阶段，你可以选择不用，官方描述。
你觉的你当前代码写的很舒服，那么为什么需要额外的引入你不了解的东西呢？当然不需要
想要知道thunk有没有意义?可以先从文档上了解
这是thunk的motivation
Redux Thunk middleware allows you to write action creators that return a function instead of an action
就是你可以dispatch(function)。
下来谈谈你的问题，不可以在异步回调之后直接手动dispatch一个action吗？
当然可以。你在异步回调之后直接dispatch，这可以啊，我觉的没什么不好。
这里主要看你对action的定义，就以网络请求为例，列个简单比较。
```
xxxAction(xxxData) {
    return {
        type: xxxType,
        data: xxxData
    }
}

// 直接放在你需要使用的地方
fetchXxxData().then((res) => {
    dispatch(xxxAction(xxx))
})

```
这种情况下，你将你xxxAction定义为一个通过数据来修改store数据的action
```
getXxxDataAction() {
    return (dispatch) => {
        fetchXxxxData().then((res) = > {
               dispatch(xxxAction(res))
        })
    }
}

使用方式
store.dispatch(getXxxDataAction())
```
这种情况下，你将这个getXxxDataAction定义为一个从后台获取数据变修改store库中的Action
其实你会发现这两个写法基本是一致的，上面那种方法是没有问题的。上面的方法可以看做是下面方法的解耦。解除了请求和修改store之间的关系。所以根本没有什么非得用谁，只是你当前的场景适合用谁。
下面方法的好处是什么，就是比如我在这个系统中，我的请求和修改数据的关系是恒定不变的，那么我不解耦的用法可能会更加的舒服。比如
A 需要获取xxx数据，并存入store中。
B 也需要获取xxx数据，并存入store中。
下面这种只需要在两个组件中去添加这句store.dispatch(getXxxDataAction())
而上面那种就必须把请求以及回调来重复写一遍，同样的代码两个路口，一旦涉及到需要修改的时候，就很容易会遗漏

标签: react.js, redux
问题：如何使用JS禁用F12和浏览器的开发者模式（控制台）
后台管理框架，想禁用用户取查看开发者模式（控制台），请问有什么JS方法或者插件可以禁用呢？比较全面的禁用，适用于多个不同浏览器的禁用。
希望有经验的能指教一下
例如这个demo站：
http://demo.larrycms.com/back...
我觉得这个站真的比较全面的禁掉了开发者模式（控制台）

回答：事先把 devtools 调成弹出式窗口的然后关掉，然后把 javascript:console.log=function(){}; 加入书签，点一下他这个你所谓的“完全禁掉了”就破功了。他是利用 console.log 打印一个对象然后覆盖这个对象的 toString 方法，一旦开发者工具存在，toString 方法就会被调用。所以破功方式就是毁掉 console.log. 
不让打开 devtools 以及不让右键查看源代码，这些都是徒劳的，我自己的电脑我在中间加个 http 代理你肯定管不着，http 代理要怎么看怎么看，把你页面上的禁用开发者工具的那段代码删掉都行。

标签: javascript, html
问题：一个中高阶难度的 JavaScript 正则场景
## 问题描述
  这是一个字符串正则替换的问题，我自己想了一晚上也想不出用纯正则就能搞定这个问题。但这个问题看起确实不复杂，所以来思否求大佬解答。
  大概的特征是这样的，我需要在一个字符串文件中查找类似 `start template template ... end` 的字符串。其中 `start` 和 `end` 是固定形式的字符串，`template` 是一个正则模式，我需要将位于 `start` 和 `end` 之间的满足 `template` 模式的字符串前面加一个前缀 `prefix`，最后我希望文件中的满足条件的字符串被修改为 `start prefix-template prefix-template ... end` 。
## 问题实例
  下面是一个例子
```
var str = "lajishuju..Ejhohaodf98  a.length+b.length+10+:rowspan=a.length + b.length+ c.length20:rowspan=a.length+b.length lajishujudsjalfj)Ufaojd";
```
  我希望能把 `:rowspan=` 和 `\d+` 之间的 `x.length` 形式的字符串修改为 `sub.x.length`。替换后的字符串应如下：
```
"lajishuju..Ejhohaodf98  a.length+b.length+10+:rowspan=sub.a.length + sub.b.length+ sub.c.length20:rowspan=a.length+b.length lajishujudsjalfj)Ufaojd"
```
  明细字符串中加入了干扰字符串，如有 `:rowspan=` 开头却没有 `\d+` 结尾的字符串，和有结尾却没开头的字符串。
## 我的想法
  我写出的正则只能利用 `(?=)` 断言排除有开头没结尾干扰字符串的干扰，无法判断是否具有合理的 `:rowspan=` 开头。
  恳请大佬指条明路，我和同学商量一下，他说不可能用一个正则一次解决这个问题。但我觉的这个模式特征这么明显，看起了也很简单，如此强大的正则不应该做不到，请大佬传道解惑！
## 另外
  题目中的“中高阶难度”是我大言不惭，毕竟我是个没怎么写过正则的菜鸡?，如有不当，请见谅！

回答：```
var str = "lajishuju..Ejhohaodf98 a.length+b.length+10+:rowspan=a.length + b.length+ c.length20:rowspan=a.length+b.length lajishujudsjalfj)Ufaojd";

var r = str.replace(/(:rowspan=)(.+?)(?=\d*:rowspan)/g, function (...m)
{
    m[2] = m[2].replace(/\b([a-z]\w*\.length)/g, 'sub.$1');

    return m[1] + m[2];
});

console.log(r);
```

标签: javascript, 正则表达式
问题：树形结构已知子节点找父节点
已知 子节点 求父节点  
例如 已知 AAA
希望 得到 A-AA-AAA的格式
data3: [{
```
      id: 1,
      label: '一级 2',
      children: [{
        id: 3,
        label: '二级 2-1',
        children: [{
          id: 4,
          label: '三级 3-1-1'
        }, {
          id: 5,
          label: '三级 3-1-2',
          disabled: true
        }]
      }, {
        id: 2,
        label: '二级 2-2',
        disabled: true,
        children: [{
          id: 6,
          label: '三级 3-2-1'
        }, {
          id: 7,
          label: '三级 3-2-2',
          disabled: true
        }]
      }]
    }],
```

回答：```
let find = (array, label) =>{
    let stack = [];
    let going = true;
    
    let walker = (array, label) => {
        array.forEach(item => {
            if (!going) return;
            stack.push(item['label']);
            if (item['label'] === label) {
                going = false;
            } else if (item['children']) {
                walker(item['children'], label);
            } else {
                stack.pop();
            }
        });
        if (going) stack.pop();
    }

    walker(array, label);

    return stack.join('-');
}

console.log(find(data, '三级 3-2-2'))
// 一级 2-二级 2-2-三级 3-2-2
```
应该是 `DFS`

标签: javascript
问题：怎么判断JSON对象中value存在重复值次数多少
怎么判断JSON对象中value存在重复值次数多少？
假设是等待处理，判断这个相同值总共多少个，然后新建 JSON，如下：
原数据：
```
[
    {name: "fcf294131", key: "处理进度", value: "等待处理"},
    {name: "fcf294131", key: "处理进度", value: "正在处理"},
    {name: "fcf294131", key: "处理进度", value: "等待处理"},
    {name: "fcf294131", key: "处理进度", value: "完成"},
    {name: "fcf294131", key: "处理进度", value: "等待处理"}
]
```
处理
```
[
    {key:"等待处理",len:3},
    {key:"正在处理",len:1},
    {key:"完成",len:1}
]
```
这个方法怎么写？

回答：```
let arr = [], // 初始数据集
    res = {}; // 结果
arr.forEach(item => {
    if(!res[item.value]) {
        res[item.value] = {
            key: item.value,
            len: 1
        }
    } else {
        res[item.value].len++;
    }
})

res = Object.values(res);
```

标签: javascript
问题：vue-cli 更新过后手机访问不显示页面内容
今天把之前学习的demo拿出来重新写，发现vue-cli 更新后不能输入ip 进行访问了，比如我的ip 是192.168.5.212 只能是默认的127.0.0.1：8080  问了群里的大神改成host：0.0.0.0 电脑输入Ip 是可以访问了（192.168.5.212:8080）但是手机访问电脑的Ip  只显示页面的标题不显示内容。（在一个局域网下）是什么原因？

回答：需要把 config/index.js里的devtool: '#eval-source-map'改为devtool:'inline-source-map'，就可以访问到了。
原有答案已失效，更新下：
package.json中找到 scripts.dev，在后面加上host参数 `--host 0.0.0.0`
```
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --host 0.0.0.0",
```

标签: vue-cli, vue.js
问题：vue-router.js里如何使用饿了么组件的弹框等的方法
methods: {
```
    open5() {
        this.$notify.info({
            title: '消息',
            message: '这是一条消息的提示消息'
        });
    }
}

这是饿了么UI的弹框方法，也是放到了单独的一个pop.vue组件

import pop from '@/components/pop'

router.beforeEach((to, from, next) => {
if (to.path === '/login' || to.path === '/') {
    next()
} else {
    if (Cookies.get('uName')) {
        next()
    } else {
        next({path: '/login'})
        alert('请重新登录')
        pop.methods.open5() //就是这里，使用报错
    }
}
```
})
这是router.js的守卫 我想在 重新登录 这使用open5这个方法，但是报错，this不对

回答：可以参考我的：
```

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
import { Notification } from 'element-ui'

// 钩子函数路由判断
router.beforeEach((to, from, next) => {
  if (to.meta.requireAuth) {
    if (localStorage.token) {
      // console.log("已有个人信息!");
      next();
    } else {
      Notification.error({message: '请先登录!', duration: 1000, position: 'bottom-right', showClose: false})
      next({
        path: '/login',
        // 跳转到登录页
      })
    }
  }
  else {
    next();
  }
})

```

标签: vue-router, vue.js
问题：这个页面用到了哪些技术？
我想知道这个如果要实现这种页面效果，需要用到哪些技术？图片又是如何存储，并且加载到页面中的？看了好像不是Flash。
https://xlysauc.yunzhan365.co...

回答：打开看控制台呀，动画是css3做的     transform: translate3d() rotate;
今天好像截图不好用，那就不贴图片了。
这种东西肯定是插件嘛。这还用想，打开source，network看看资源，然后看看特别的class类名。发现了fliphtml5这么个东西，百度一下
传送门

标签: 前端, javascript, php
问题：请教个问题，关于项目开发的
例如在java开发时，前后端分离，那数据库设计、前端、后端是怎么分配的？-->数据库设计是有主要的人员设计吗？前后端分离，是前端做完再把东西和接口让后端做？

回答：数据库可以由专人负责，也可以由业务告知需求，让后台的人设计。
步骤1
前端和后端商定可能需要用到的接口，然后开发时可以用
`http://www.example.com/api/v1/GetUserInfo`
其中通过 `/api/v1` 来区分不同时期的版本，在约定好接口（域、参数列表、返回参考）后，就可以开始正式开发：
步骤二
前端通过 `mock` 来模拟数据，简单来说就是根据前边的约定自己写死一个假数据先用着，现在也有专门开个 `mock server` 来提供通信环境的模拟；
后端则可以通过单元测试来检查接口。
步骤三
当开发到一定程度后，可以两边开始实际对接一下，找出问题，进行沟通，修改一开始的接口约定。
重复步骤一到三，因为长期项目维护的话，就不会有尽头了。

标签: java, html, css
问题：学了半年前端，如何去理解那些框架的工作原理，比如webpack，vue
最近很疑惑，究竟要熟练到什么程度，才能对前端的一些框架、工作流等工作原理比较熟悉。去看webpack的文档，感觉太晦涩难懂了。。。
感觉一直是在做一名搬运工，只知道拿别人的东西来用，但却不知道为什么，不懂如何创造

回答：思考当然很重要，但是中间决不能缺少代码从量变到质变的过程。
有了这个过程之后，思考的作用才能得以体现。
你现在有这样的心态很好，不能急于求成。不要让这份对代码的好奇与热爱的感觉消失，
总有一天我相信你用经验与技术写成的文章会被万人收藏!
(送给自己，和每一个在路上的执着的人)

标签: javascript, webpack, 前端
问题：laravel 5想自定义全局函数，怎么弄呢？
想把
```
//生成友好时间形式
function  friendly_date( $from ){
    static $now = NULL;
    $now == NULL && $now = time();
    ! is_numeric( $from ) && $from = strtotime( $from );
    $seconds = $now - $from;
    $minutes = floor( $seconds / 60 );
    $hours   = floor( $seconds / 3600 );
    $day     = round( ( strtotime( date( 'Y-m-d', $now ) ) - strtotime( date( 'Y-m-d', $from ) ) ) / 86400 );
    if( $seconds == 0 ){
        return '刚刚';
    }
    if( ( $seconds >= 0 ) && ( $seconds <= 60 ) ){
        return "{$seconds}秒前";
    }
    if( ( $minutes >= 0 ) && ( $minutes <= 60 ) ){
        return "{$minutes}分钟前";
    }
    if( ( $hours >= 0 ) && ( $hours <= 24 ) ){
        return "{$hours}小时前";
    }
    if( ( date( 'Y' ) - date( 'Y', $from ) ) > 0 ) {
        return date( 'Y-m-d', $from );
    }
    
    switch( $day ){
        case 0:
            return date( '今天H:i', $from );
        break;
        
        case 1:
            return date( '昨天H:i', $from );
        break;
        
        default:
            //$day += 1;
            return "{$day} 天前";
        break;
    }
}
```
放入函数库，怎么放呢

回答：在app/Helpers/(目录可以自己随便来) 下新建一个文件 functions.php 
在functions.php 中加入这个方法
然后在
bootstrap/autoload.php 中添加
```
require __DIR__.'/../app/Helpers/functions.php';
```
或者在
composer.json 中的 autoload 下增加
```
"files": [
    "app/Helpers/functions.php"
]
```
```
...
"autoload": {
    "classmap": [
        "database"
    ],
    "psr-4": {
        "App\\": "app/"
    },
    "files": [
        "app/helpers/functions.php"
    ]
},

...
```
然后执行：
```
composer dump-auto
```

标签: laravel, php
问题：有没有遇到过只在 Android 7.1 机型上报告的由Toast引起的BadTokenException错误？
由Bugly统计上报，只发生在7.1.1和7.1.2机型上，目前没有复现，所以还没排查出是哪里出了问题。
错误堆栈
```
# main(1)
android.view.WindowManager$BadTokenException
    Unable to add window -- token android.os.BinderProxy@7f652b2 is not valid; is your activity running?
    android.view.ViewRootImpl.setView(ViewRootImpl.java:826)
    android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:369)
    android.view.WindowManagerImpl.addView(WindowManagerImpl.java:94)
    android.widget.Toast$TN.handleShow(Toast.java:459)
    android.widget.Toast$TN$2.handleMessage(Toast.java:342)
    android.os.Handler.dispatchMessage(Handler.java:102)
    android.os.Looper.loop(Looper.java:185)
    android.app.ActivityThread.main(ActivityThread.java:6493)
    java.lang.reflect.Method.invoke(Native Method)
    com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:916)
    com.android.internal.os.ZygoteInit.main(ZygoteInit.java:806)
```

回答：这个问题由于targetSDKVersion升到26之后，在7.1.1机型上概率性出现。稳定复现的步骤是，在Toast.show()之后，UI线程做了耗时的操作阻塞了Handler message的处理，如使用Thread.sleep(5000)，然后这个崩溃就出现了。原因是7.1.1系统对TYPE_TOAST的Window类型做了超时限制，绑定了Window Token，最长超时时间是3.5s，如果UI在这段时间内没有执行完，Toast.show()内部的handler message得不到执行，NotificationManageService那端会把这个Toast取消掉，同时把Toast对于的window token置为无效。等App端真正需要显示Toast时，因为window token已经失效，ViewRootImpl就抛出了上面的异常。
Android 8.0上面，google意识到这个bug，在Toast的内部加了try-catch保护。目前只有7.1.1上面的Toast存在这个问题，崩溃在系统源码里。APP层可以通过自定义Toast类，反射替换TN的内部成员变量mHandler，从而添加try-catch做到workaround，所有使用Toast的地方都使用这个自定义的，不要直接使用系统原生的。

标签: android
问题：如何写一个python脚本，可以同时执行 python3 和 Python2？
不管是在 Python2 还是在 Python3 中，我们可以通过以下方法得到关键字列表：
```
import keyword
keyword.kwlist
```
现在我们可以得到两个版本的 Python 的关键字，手工赋值：
```
kw2= ['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'with', 'yield'] # Python2 关键字列表

kw3 = ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'] # Python3 的关键字列表

```
使用内建的 difflib 模块，我们可以比较出增减的关键字：
```
d = difflib.Differ()
diff = d.compare(kw2, kw3)
print '\n'.join(diff)
```
得到以下内容：
```
+ False
+ None
+ True
  and
  as
  assert
  break
  class
  continue
  def
  del
  elif
  else
  except
- exec
  finally
  for
  from
  global
  if
  import
  in
  is
  lambda
+ nonlocal
  not
  or
  pass
- print
  raise
  return
  try
  while
  with
  yield
```
那么问题来了，不管是使用 Python2 还是 Python3 ，我如何做，才能使用一个脚本，直接实现上面的结果？？？

回答：直接上代码，自己体会吧。
```
import os
import json
import difflib
def test():
    cmd2 = 'E:/Python27/python.exe -c "import keyword;import json;print (json.dumps(keyword.kwlist))"'
    cmd3 = 'C:/Python36/python.exe -c "import keyword;import json;print (json.dumps(keyword.kwlist))"'
    res2 = json.loads(os.popen(cmd2).read())
    res3 = json.loads(os.popen(cmd3).read())
    d = difflib.Differ()
    diff = d.compare(res2, res3)
    print '\n'.join(diff)
if __name__ == '__main__':
    test()
```

标签: python
问题：对express 应用级中间件next('route') 方法实例的疑惑
对`express`官网 的实例有点疑惑，不知道为什么这样书写.
官网的代码是这样的
```
// 一个中间件栈，处理指向 /user/:id 的 GET 请求
app.get('/user/:id', function (req, res, next) {
  // 如果 user id 为 0, 跳到下一个路由
  if (req.params.id == 0) next('route');
  // 否则将控制权交给栈中下一个中间件
  else next(); //
}, function (req, res, next) {
  // 渲染常规页面
  res.render('regular');
});

// 处理 /user/:id， 渲染一个特殊页面
app.get('/user/:id', function (req, res, next) {
  res.render('special');
});

```
```
app.get('/user/:id', function (req, res, next) {
  if (req.params.id == 0) {
    res.render('special');
  } else {
    res.render('regular');
  };
})
```
附上网址 (http://www.expressjs.com.cn/g...
`应用级中间件`的第四个实例 `next('route')` 方法

回答：## 先回答您的问题
首先，官方这段代码实现的效果，跟您修改后代码的效果是差不多的。
其次，官网这段代码的主要目的，是告诉使用者，`next('route')`的用途。
最后，至于官网为什么要这样写，得从Express的路由机制谈起。
## Express路由分组机制
Express的路由内部实现比较复杂，这里只挑跟题目有关的讲。
Express中，路由是以组的形式添加的。什么意思呢，可以看下面伪代码
```
app.get('/user/:id', fn1, fn2, fn3);
app.get('/user/:id', fn4, fn5, fn6);
```
在内部，Express把上面添加的路由，分成了两个组。继续看伪代码，可以看到，路由在内部被分成了两个组。
```
var stack = [
  {path: '/user/:id', fns: [fn1, fn2, fn3], // 路由组1
  {path: '/user/:id', fns: [fn4, fn5, fn5] // 路由组2
];
```
路由匹配就是个遍历的过程，略。
## next('route')是干嘛的
答案：跳过当前路由分组中，剩余的handler（中间件）
如果没有`next('route')`，一路`next()`调用下去的话，调用顺序是这样的：
```
fn1 -> fn2 -> fn3 -> fn4 -> fn5 -> fn6
```
假设某些情况下，在执行了`fn1`后，想要跳过`fn2`、`fn3`，怎么办？（比如您举的例子）
答案就是在`fn1`里调用`next('route')`。
然后就变成了
```
fn1 -> fn4 -> fn5 -> fn6
```
完。

标签: node.js, express, javascript
问题：应该用forEach改变数组的值吗?
由于js中的数组是引用类型，所以可以利用类似指针的特性通过改变另一个变量去修改原始的值。我认为这其实是js中的缺陷，所以我不喜欢利用这个"缺陷"去实现一些功能，在最近的一次code review中，同事指出了这个问题。所以我希望有更多朋友能给我一些建议。
下面就是简单的例子。
```
let arr = [{
    a:1,
    b:2,
}, {
    a:3,
    b:4,
}];
```
如果有以上数组，我需要将每一项的a改为3。大概有两种写法，一种是用forEach，另一种是用map来返回一个新数组(暂不考虑for循环)。
forEach:
```
arr.forEach((item) => {
    item.a = 3; 
});
```
map:
```
arr = arr.map((item) => {   //  有同事指出应该声明一个新变量来存储map的结果，这个建议我认为是对的。
    item.a = 3;
    return item;
});
```

回答：补充下，刚才没仔细看题目。题目的`map`方法不够“纯粹”，实际上还是直接修改了每个`item`的属性，要想不影响原有对象，应该这么写：
```
arr = arr.map((item) => {   //  有同事指出应该声明一个新变量来存储map的结果，这个建议我认为是对的。
    return {
        ...item,
        a:3
    }
});
```
==============
`map`方法体现的是数据不可变的思想。该思想认为所有的数据都是不能改变的，只能通过生成新的数据来达到修改的目的，因此直接对数组元素或对象属性进行操作的行为都是不可取的。这种思想其实有很多好处，最直接的就是避免了数据的隐式修改。`immutable.js`是实现数据不可变的一个库，可通过专属的API对引用类型进行操作，每次形成一个新的对象。
但具体到项目中还是要看团队的要求，都用或者都不用。单单局部使用是没有效果的。
如果使用了`React + Redux` 的技术栈，是比较推荐使用的
另外有一点，`forEach`和`map`还存在一个编程思想的区别，前者是命令式编程，后者是声明式编程，如果项目的风格是声明式的，比如`React`，那么后者显然更统一。

标签: javascript, 前端
问题：关于和后端对接数据，空值判断的问题
大家在拿到后端的数据，要绑到页面上的时候，空值判断一般是怎么处理的？
比如说前端要一个`List`，`Array`类型，但后端没查到，你想着会给你个`[]`，但就给你返回个`null`，这就导致前端取`length`的时候就报错了，难道每次都要写`if`判断吗？
```
if (res.list !== null) {
    this.list = res.list;
}
```
请问有什么干净效率的办法？

回答：假如后端返回res对象，res.body希望是个数组，但是实际返回一个null
那么在不考虑深复制浅复制问题的前提下
```
let newArray = res.body || []

console.log(newArray.length)
```
这样至少可以保证不会得到null

标签: 前端, javascript, vue.js