Instruction:
关于promise中reject和catch的问题
reject和catch是否都会执行，或者只执行其中一个，分别在什么情况下执行？

Output:
### 一、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的第二个回调


Instruction:
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;
 };
```
请教下有没有更好的方法？我觉得自己方法有点烂。

Output:
```
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)
```


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

Output:
说下个人目前在用的分布
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层就出现了。

```


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

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

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

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


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

Output:
大致意思就是，你可以用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;
});
```


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

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


Instruction:
CSS3 Transform 引起的 z-index "失效"
两个页面使用的css3 Transform动画之后，页面下子元素的z-index就失效了，就算设置的再大的值也不会起作用，但是一个页面的时候是没有问题的

Output:
这里涉及到一个`stacking context`（有人翻译为`层叠上下文`）的概念。
给元素设置`transform`属性会创建一个新的`stacking context`。
请看下面的具体讲解：
注：以下两个例子最好先想象一下预览效果，再查看结果预览页面。
先上一个小例子（你可以在https://jsfiddle.net/运行）：
```html
'<div class="test test-1">
</div>
<div class="test test-2">
</div>
```
```css
.test {
    width: 100px;
    height: 100px;
}

.test-1 {
    -webkit-transform: scale(.9);
    transform: scale(.9);
    /*opacity: 0.9*/
    background: #f20;
}

.test-2 {
    margin-top: -50px;
    background: #000;
}
```
上面这个例子中，两个div都没有设置任何`position`，如果没有给`test-1`添加`transform`属性的话，第二个div将会覆盖第一个div。但是如果设置了`transform`的话呢？由于`transform`会创建一个新的`stacking context`。在层级关系上就要比`test-2`高一级，因此，显示在上面。
再来一个例子，
```html
'<div class="test test-1">
</div>
<div class="test test-2">
</div>
```
```css
.test {
    width: 100px;
    height: 100px;
}

.test-1 {
    position: relative;
    background: #f20;
}

.test-2 {
    -webkit-transform: scale(.9);
    transform: scale(.9);
    margin-top: -50px;
    background: #000;
}
```
这个例子了是对上面那个例子作了个简单的修改。我们给`test-1`添加了一个`position: relative`，`test-2`没有任何`position`属性，只是添加了一个`transform`的属性。如果不看预览页面的话，可能会以为`test-1`会显示在`test-2`上方，其实不然。由于`transform`会创建新的`stacking context`，同时`test-2`在文档中又处于`test-1`的后面，所以最终的效果是`test-2`显示在`test-1`的上方。
那么问题来了，哪些情况下会创建新的`stacking context`呢？
MDN上有相关的介绍：
- the root element (HTML),
- positioned (absolutely or relatively) with a z-index value other than "auto",
- a flex item with a z-index value other than "auto",
- elements with an opacity value less than 1,
- elements with a transform value other than "none",
- elements with a mix-blend-mode value other than "normal",
- elements with isolation set to "isolate", on mobile WebKit and Chrome 22+, position: fixed always creates a new stacking context, even when z-index is "auto",
- specifing any attribute above in will-change even you don't write themselves directly

其中，第二条是我们平时最常见的，另外几条加粗的会随着CSS3的普及越来越常见。令我感到惊奇是，`opacity`竟然也会创建新的`stacking context`，你可以试着将上面两个例子中的`transform`换成`opacity`，会得到同样的效果。
值得注意的是，介绍`stacking context`的文章显然不像介绍CSS中另外一个“上下文”——`Block formatting context`（块级格式上下文）的文章多，原因可能是，我们在平常很少遇到`stacking context`相关的问题，但是随着CSS3的普及，这方面的问题可能会多起来的。
这也算是CSS中一个比较有趣而且有用的知识点，之前在工作中遇到过一次，正好此处有人问到，特整理了一下，供参考。
### 补充
说了这么多，回到你这个具体的问题上来，由于你没有提供具体的代码，不好说出具体的问题所在，但可以推测出你的代码中可能有类似下面这个例子中的结构。你给`.child`设置再大的`z-index`都没有用。但是如果将`.inner`的`transform`去掉就不一样了。试试看。
```html
<div class="test test-1">
    <div class="inner">
        <div class="child">
            Child
        </div>
    </div>
</div>
<div class="test test-2">
</div>
```
```css
.test {
    width: 100px;
    height: 100px;
}

.test-1 {
    position: relative;
    background: #f20;
}

.inner {
    width: 80px;
    height: 80px;
    transform: scale(1); /*此处会产生新的stacking context*/
    background: green;
}

.child {
    position: absolute;
    bottom: 15px;
    color: #fff;
    font-size: 30px;
    z-index: 1000;
}

.test-2 {
    position: relative;
    margin-top: -50px;
    background: #000;
}
```
### 参考链接
- [The stacking context](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_context)


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

Output:
方案一，`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);
```


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

Output:
```
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 处理


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

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


Instruction:
看一个题，谁能帮忙解释一下？这是一个关于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. ...（涉及的没提到的）

Output:
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))
```


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

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

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

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

祝你做个好的 contributor。


Instruction:
一道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]]
```

Output:
```
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))
```


Instruction:
路径中`@/`代表什么意思，与`./`有何区别呢？
我在一个项目代码中看到：
```
import store from '@/vuex/store'

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

```
有什么区别？

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


Instruction:
vue 项目，ios上audio音频 无法自动播放
spa页面，初次进入音乐播放界面的时候，在ios上无法自动播放，通过play()方法还是无法实现播放。有什么方法可以解决的

Output:
我是这样做的：
```
//--创建页面监听，页面加载完毕--触发音频播放
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();
});
```


Instruction:
分享一道面试题，请指点结果为何是undefined
```
if(!("a" in window)){
    var a = 10;
}
console.log(a); // undefined

```

Output:
```
因为变量提升到作用域顶部

//变量提升
var a ;

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

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


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

Output:
首先，我不知道你入和对意义的定义？性能变好？代码可读性增加？扩展性变强？
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())
而上面那种就必须把请求以及回调来重复写一遍，同样的代码两个路口，一旦涉及到需要修改的时候，就很容易会遗漏


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

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


Instruction:
一个中高阶难度的 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=` 开头。
  恳请大佬指条明路，我和同学商量一下，他说不可能用一个正则一次解决这个问题。但我觉的这个模式特征这么明显，看起了也很简单，如此强大的正则不应该做不到，请大佬传道解惑！
## 另外
  题目中的“中高阶难度”是我大言不惭，毕竟我是个没怎么写过正则的菜鸡?，如有不当，请见谅！

Output:
```
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);
```


Instruction:
树形结构已知子节点找父节点
已知 子节点 求父节点
例如 已知 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
        }]
      }]
    }],
```

Output:
```
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`


Instruction:
怎么判断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}
]
```
这个方法怎么写？

Output:
```
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);
```


Instruction:
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  只显示页面的标题不显示内容。（在一个局域网下）是什么原因？

Output:
需要把 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",
```


Instruction:
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不对

Output:
可以参考我的：
```

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();
  }
})

```


Instruction:
java如何获取实时cpu使用情况？
问题：java如何获取实时cpu使用情况？
我是一个java新手，我想知道如何实时获得cpu使用情况？也就是动态的，随着cpu情况，返回不同的cpu使用信息，我猜这个程序需要一直运行。非常抱歉，我不知道这么做，也没有相关的代码，但是我非常想知道，能提供一个案例吗？
我在搜索引擎上查找了很多信息都没有相关的代码，
这是我搜索到的，但这一个不是实时的，我需要一个能实时观察的，提前感谢
我搜索到的地址：https://www.cnblogs.com/Rozdy...

Output:
首先编写一个MonitorInfoBean类，用来装载监控的一些信息，包括物理内存、剩余的物理内存、已使用的物理内存、内存使用率等字段，该类的代码如下：
```
package com.amgkaka.performance;

/** *//**
 * 监视信息的JavaBean类.
 * @author  amg
 * @version 1.0
 * Creation date: 2008-4-25 - 上午10:37:00
 */
public class MonitorInfoBean {
    /** *//** 可使用内存. */
    private long totalMemory;

    /** *//** 剩余内存. */
    private long freeMemory;

    /** *//** 最大可使用内存. */
    private long maxMemory;

    /** *//** 操作系统. */
    private String osName;

    /** *//** 总的物理内存. */
    private long totalMemorySize;

    /** *//** 剩余的物理内存. */
    private long freePhysicalMemorySize;

    /** *//** 已使用的物理内存. */
    private long usedMemory;

    /** *//** 线程总数. */
    private int totalThread;

    /** *//** cpu使用率. */
    private double cpuRatio;

    public long getFreeMemory() {
        return freeMemory;
    }

    public void setFreeMemory(long freeMemory) {
        this.freeMemory = freeMemory;
    }

    public long getFreePhysicalMemorySize() {
        return freePhysicalMemorySize;
    }

    public void setFreePhysicalMemorySize(long freePhysicalMemorySize) {
        this.freePhysicalMemorySize = freePhysicalMemorySize;
    }

    public long getMaxMemory() {
        return maxMemory;
    }

    public void setMaxMemory(long maxMemory) {
        this.maxMemory = maxMemory;
    }

    public String getOsName() {
        return osName;
    }

    public void setOsName(String osName) {
        this.osName = osName;
    }

    public long getTotalMemory() {
        return totalMemory;
    }

    public void setTotalMemory(long totalMemory) {
        this.totalMemory = totalMemory;
    }

    public long getTotalMemorySize() {
        return totalMemorySize;
    }

    public void setTotalMemorySize(long totalMemorySize) {
        this.totalMemorySize = totalMemorySize;
    }

    public int getTotalThread() {
        return totalThread;
    }

    public void setTotalThread(int totalThread) {
        this.totalThread = totalThread;
    }

    public long getUsedMemory() {
        return usedMemory;
    }

    public void setUsedMemory(long usedMemory) {
        this.usedMemory = usedMemory;
    }

    public double getCpuRatio() {
        return cpuRatio;
    }

    public void setCpuRatio(double cpuRatio) {
        this.cpuRatio = cpuRatio;
    }
}

package com.amgkaka.performance;

/** *//**
 * 监视信息的JavaBean类.
 * @author  amg
 * @version 1.0
 * Creation date: 2008-4-25 - 上午10:37:00
 */
public class MonitorInfoBean {
    /** *//** 可使用内存. */
    private long totalMemory;

    /** *//** 剩余内存. */
    private long freeMemory;

    /** *//** 最大可使用内存. */
    private long maxMemory;

    /** *//** 操作系统. */
    private String osName;

    /** *//** 总的物理内存. */
    private long totalMemorySize;

    /** *//** 剩余的物理内存. */
    private long freePhysicalMemorySize;

    /** *//** 已使用的物理内存. */
    private long usedMemory;

    /** *//** 线程总数. */
    private int totalThread;

    /** *//** cpu使用率. */
    private double cpuRatio;

    public long getFreeMemory() {
        return freeMemory;
    }

    public void setFreeMemory(long freeMemory) {
        this.freeMemory = freeMemory;
    }

    public long getFreePhysicalMemorySize() {
        return freePhysicalMemorySize;
    }

    public void setFreePhysicalMemorySize(long freePhysicalMemorySize) {
        this.freePhysicalMemorySize = freePhysicalMemorySize;
    }

    public long getMaxMemory() {
        return maxMemory;
    }

    public void setMaxMemory(long maxMemory) {
        this.maxMemory = maxMemory;
    }

    public String getOsName() {
        return osName;
    }

    public void setOsName(String osName) {
        this.osName = osName;
    }

    public long getTotalMemory() {
        return totalMemory;
    }

    public void setTotalMemory(long totalMemory) {
        this.totalMemory = totalMemory;
    }

    public long getTotalMemorySize() {
        return totalMemorySize;
    }

    public void setTotalMemorySize(long totalMemorySize) {
        this.totalMemorySize = totalMemorySize;
    }

    public int getTotalThread() {
        return totalThread;
    }

    public void setTotalThread(int totalThread) {
        this.totalThread = totalThread;
    }

    public long getUsedMemory() {
        return usedMemory;
    }

    public void setUsedMemory(long usedMemory) {
        this.usedMemory = usedMemory;
    }

    public double getCpuRatio() {
        return cpuRatio;
    }

    public void setCpuRatio(double cpuRatio) {
        this.cpuRatio = cpuRatio;
    }
}

```
接着编写一个获得当前的监控信息的接口，该类的代码如下所示：
```
package com.amgkaka.performance;

/** *//**
 * 获取系统信息的业务逻辑类接口.
 * @author amg * @version 1.0
 * Creation date: 2008-3-11 - 上午10:06:06
 */
public interface IMonitorService {
    /** *//**
     * 获得当前的监控对象.
     * @return 返回构造好的监控对象
     * @throws Exception
     * @author amgkaka
     * Creation date: 2008-4-25 - 上午10:45:08
     */
    public MonitorInfoBean getMonitorInfoBean() throws Exception;

}

package com.amgkaka.performance;

/** *//**
 * 获取系统信息的业务逻辑类接口.
 * @author amg * @version 1.0
 * Creation date: 2008-3-11 - 上午10:06:06
 */
public interface IMonitorService {
    /** *//**
     * 获得当前的监控对象.
     * @return 返回构造好的监控对象
     * @throws Exception
     * @author amgkaka
     * Creation date: 2008-4-25 - 上午10:45:08
     */
    public MonitorInfoBean getMonitorInfoBean() throws Exception;

}

```
该类的实现类MonitorServiceImpl如下所示：
```
package com.amgkaka.performance;

import java.io.InputStreamReader;
import java.io.LineNumberReader;

import sun.management.ManagementFactory;

import com.sun.management.OperatingSystemMXBean;

/** *//**
 * 获取系统信息的业务逻辑实现类.
 * @author amg * @version 1.0 Creation date: 2008-3-11 - 上午10:06:06
 */
public class MonitorServiceImpl implements IMonitorService {
    //可以设置长些，防止读到运行此次系统检查时的cpu占用率，就不准了
    private static final int CPUTIME = 5000;

    private static final int PERCENT = 100;

    private static final int FAULTLENGTH = 10;

    /** *//**
     * 获得当前的监控对象.
     * @return 返回构造好的监控对象
     * @throws Exception
     * @author amg     * Creation date: 2008-4-25 - 上午10:45:08
     */
    public MonitorInfoBean getMonitorInfoBean() throws Exception {
        int kb = 1024;

        // 可使用内存
        long totalMemory = Runtime.getRuntime().totalMemory() / kb;
        // 剩余内存
        long freeMemory = Runtime.getRuntime().freeMemory() / kb;
        // 最大可使用内存
        long maxMemory = Runtime.getRuntime().maxMemory() / kb;

        OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory
                .getOperatingSystemMXBean();

        // 操作系统
        String osName = System.getProperty("os.name");
        // 总的物理内存
        long totalMemorySize = osmxb.getTotalPhysicalMemorySize() / kb;
        // 剩余的物理内存
        long freePhysicalMemorySize = osmxb.getFreePhysicalMemorySize() / kb;
        // 已使用的物理内存
        long usedMemory = (osmxb.getTotalPhysicalMemorySize() - osmxb
                .getFreePhysicalMemorySize())
                / kb;

        // 获得线程总数
        ThreadGroup parentThread;
        for (parentThread = Thread.currentThread().getThreadGroup(); parentThread
                .getParent() != null; parentThread = parentThread.getParent())
            ;
        int totalThread = parentThread.activeCount();

        double cpuRatio = 0;
        if (osName.toLowerCase().startsWith("windows")) {
            cpuRatio = this.getCpuRatioForWindows();
        }

        // 构造返回对象
        MonitorInfoBean infoBean = new MonitorInfoBean();
        infoBean.setFreeMemory(freeMemory);
        infoBean.setFreePhysicalMemorySize(freePhysicalMemorySize);
        infoBean.setMaxMemory(maxMemory);
        infoBean.setOsName(osName);
        infoBean.setTotalMemory(totalMemory);
        infoBean.setTotalMemorySize(totalMemorySize);
        infoBean.setTotalThread(totalThread);
        infoBean.setUsedMemory(usedMemory);
        infoBean.setCpuRatio(cpuRatio);
        return infoBean;
    }

    /** *//**
     * 获得CPU使用率.
     * @return 返回cpu使用率
     * @author amg     * Creation date: 2008-4-25 - 下午06:05:11
     */
    private double getCpuRatioForWindows() {
        try {
            String procCmd = System.getenv("windir")
                    + "//system32//wbem//wmic.exe process get Caption,CommandLine,"
                    + "KernelModeTime,ReadOperationCount,ThreadCount,UserModeTime,WriteOperationCount";
            // 取进程信息
            long[] c0 = readCpu(Runtime.getRuntime().exec(procCmd));
            Thread.sleep(CPUTIME);
            long[] c1 = readCpu(Runtime.getRuntime().exec(procCmd));
            if (c0 != null && c1 != null) {
                long idletime = c1[0] - c0[0];
                long busytime = c1[1] - c0[1];
                return Double.valueOf(
                        PERCENT * (busytime) / (busytime + idletime))
                        .doubleValue();
            } else {
                return 0.0;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            return 0.0;
        }
    }

    /** *//**
     * 读取CPU信息.
     * @param proc
     * @return
     * @author amg     * Creation date: 2008-4-25 - 下午06:10:14
     */
    private long[] readCpu(final Process proc) {
        long[] retn = new long[2];
        try {
            proc.getOutputStream().close();
            InputStreamReader ir = new InputStreamReader(proc.getInputStream());
            LineNumberReader input = new LineNumberReader(ir);
            String line = input.readLine();
            if (line == null || line.length() < FAULTLENGTH) {
                return null;
            }
            int capidx = line.indexOf("Caption");
            int cmdidx = line.indexOf("CommandLine");
            int rocidx = line.indexOf("ReadOperationCount");
            int umtidx = line.indexOf("UserModeTime");
            int kmtidx = line.indexOf("KernelModeTime");
            int wocidx = line.indexOf("WriteOperationCount");
            long idletime = 0;
            long kneltime = 0;
            long usertime = 0;
            while ((line = input.readLine()) != null) {
                if (line.length() < wocidx) {
                    continue;
                }
                // 字段出现顺序：Caption,CommandLine,KernelModeTime,ReadOperationCount,
                // ThreadCount,UserModeTime,WriteOperation
                String caption = Bytes.substring(line, capidx, cmdidx - 1)
                        .trim();
                String cmd = Bytes.substring(line, cmdidx, kmtidx - 1).trim();
                if (cmd.indexOf("wmic.exe") >= 0) {
                    continue;
                }
                // log.info("line="+line);
                if (caption.equals("System Idle Process")
                        || caption.equals("System")) {
                    idletime += Long.valueOf(
                            Bytes.substring(line, kmtidx, rocidx - 1).trim())
                            .longValue();
                    idletime += Long.valueOf(
                            Bytes.substring(line, umtidx, wocidx - 1).trim())
                            .longValue();
                    continue;
                }

                kneltime += Long.valueOf(
                        Bytes.substring(line, kmtidx, rocidx - 1).trim())
                        .longValue();
                usertime += Long.valueOf(
                        Bytes.substring(line, umtidx, wocidx - 1).trim())
                        .longValue();
            }
            retn[0] = idletime;
            retn[1] = kneltime + usertime;
            return retn;
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                proc.getInputStream().close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /** *//**
     * 测试方法.
     * @param args
     * @throws Exception
     * @author amg     * Creation date: 2008-4-30 - 下午04:47:29
     */
    public static void main(String[] args) throws Exception {
        IMonitorService service = new MonitorServiceImpl();
        MonitorInfoBean monitorInfo = service.getMonitorInfoBean();
        System.out.println("cpu占有率=" + monitorInfo.getCpuRatio());

        System.out.println("可使用内存=" + monitorInfo.getTotalMemory());
        System.out.println("剩余内存=" + monitorInfo.getFreeMemory());
        System.out.println("最大可使用内存=" + monitorInfo.getMaxMemory());

        System.out.println("操作系统=" + monitorInfo.getOsName());
        System.out.println("总的物理内存=" + monitorInfo.getTotalMemorySize() + "kb");
        System.out.println("剩余的物理内存=" + monitorInfo.getFreeMemory() + "kb");
        System.out.println("已使用的物理内存=" + monitorInfo.getUsedMemory() + "kb");
        System.out.println("线程总数=" + monitorInfo.getTotalThread() + "kb");
    }
}

package com.amgkaka.performance;

import java.io.InputStreamReader;
import java.io.LineNumberReader;

import sun.management.ManagementFactory;

import com.sun.management.OperatingSystemMXBean;

/** *//**
 * 获取系统信息的业务逻辑实现类.
 * @author amg * @version 1.0 Creation date: 2008-3-11 - 上午10:06:06
 */
public class MonitorServiceImpl implements IMonitorService {
    //可以设置长些，防止读到运行此次系统检查时的cpu占用率，就不准了
    private static final int CPUTIME = 5000;

    private static final int PERCENT = 100;

    private static final int FAULTLENGTH = 10;

    /** *//**
     * 获得当前的监控对象.
     * @return 返回构造好的监控对象
     * @throws Exception
     * @author amg     * Creation date: 2008-4-25 - 上午10:45:08
     */
    public MonitorInfoBean getMonitorInfoBean() throws Exception {
        int kb = 1024;

        // 可使用内存
        long totalMemory = Runtime.getRuntime().totalMemory() / kb;
        // 剩余内存
        long freeMemory = Runtime.getRuntime().freeMemory() / kb;
        // 最大可使用内存
        long maxMemory = Runtime.getRuntime().maxMemory() / kb;

        OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory
                .getOperatingSystemMXBean();

        // 操作系统
        String osName = System.getProperty("os.name");
        // 总的物理内存
        long totalMemorySize = osmxb.getTotalPhysicalMemorySize() / kb;
        // 剩余的物理内存
        long freePhysicalMemorySize = osmxb.getFreePhysicalMemorySize() / kb;
        // 已使用的物理内存
        long usedMemory = (osmxb.getTotalPhysicalMemorySize() - osmxb
                .getFreePhysicalMemorySize())
                / kb;

        // 获得线程总数
        ThreadGroup parentThread;
        for (parentThread = Thread.currentThread().getThreadGroup(); parentThread
                .getParent() != null; parentThread = parentThread.getParent())
            ;
        int totalThread = parentThread.activeCount();

        double cpuRatio = 0;
        if (osName.toLowerCase().startsWith("windows")) {
            cpuRatio = this.getCpuRatioForWindows();
        }

        // 构造返回对象
        MonitorInfoBean infoBean = new MonitorInfoBean();
        infoBean.setFreeMemory(freeMemory);
        infoBean.setFreePhysicalMemorySize(freePhysicalMemorySize);
        infoBean.setMaxMemory(maxMemory);
        infoBean.setOsName(osName);
        infoBean.setTotalMemory(totalMemory);
        infoBean.setTotalMemorySize(totalMemorySize);
        infoBean.setTotalThread(totalThread);
        infoBean.setUsedMemory(usedMemory);
        infoBean.setCpuRatio(cpuRatio);
        return infoBean;
    }

    /** *//**
     * 获得CPU使用率.
     * @return 返回cpu使用率
     * @author amg     * Creation date: 2008-4-25 - 下午06:05:11
     */
    private double getCpuRatioForWindows() {
        try {
            String procCmd = System.getenv("windir")
                    + "//system32//wbem//wmic.exe process get Caption,CommandLine,"
                    + "KernelModeTime,ReadOperationCount,ThreadCount,UserModeTime,WriteOperationCount";
            // 取进程信息
            long[] c0 = readCpu(Runtime.getRuntime().exec(procCmd));
            Thread.sleep(CPUTIME);
            long[] c1 = readCpu(Runtime.getRuntime().exec(procCmd));
            if (c0 != null && c1 != null) {
                long idletime = c1[0] - c0[0];
                long busytime = c1[1] - c0[1];
                return Double.valueOf(
                        PERCENT * (busytime) / (busytime + idletime))
                        .doubleValue();
            } else {
                return 0.0;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            return 0.0;
        }
    }

    /** *//**
     * 读取CPU信息.
     * @param proc
     * @return
     * @author amg     * Creation date: 2008-4-25 - 下午06:10:14
     */
    private long[] readCpu(final Process proc) {
        long[] retn = new long[2];
        try {
            proc.getOutputStream().close();
            InputStreamReader ir = new InputStreamReader(proc.getInputStream());
            LineNumberReader input = new LineNumberReader(ir);
            String line = input.readLine();
            if (line == null || line.length() < FAULTLENGTH) {
                return null;
            }
            int capidx = line.indexOf("Caption");
            int cmdidx = line.indexOf("CommandLine");
            int rocidx = line.indexOf("ReadOperationCount");
            int umtidx = line.indexOf("UserModeTime");
            int kmtidx = line.indexOf("KernelModeTime");
            int wocidx = line.indexOf("WriteOperationCount");
            long idletime = 0;
            long kneltime = 0;
            long usertime = 0;
            while ((line = input.readLine()) != null) {
                if (line.length() < wocidx) {
                    continue;
                }
                // 字段出现顺序：Caption,CommandLine,KernelModeTime,ReadOperationCount,
                // ThreadCount,UserModeTime,WriteOperation
                String caption = Bytes.substring(line, capidx, cmdidx - 1)
                        .trim();
                String cmd = Bytes.substring(line, cmdidx, kmtidx - 1).trim();
                if (cmd.indexOf("wmic.exe") >= 0) {
                    continue;
                }
                // log.info("line="+line);
                if (caption.equals("System Idle Process")
                        || caption.equals("System")) {
                    idletime += Long.valueOf(
                            Bytes.substring(line, kmtidx, rocidx - 1).trim())
                            .longValue();
                    idletime += Long.valueOf(
                            Bytes.substring(line, umtidx, wocidx - 1).trim())
                            .longValue();
                    continue;
                }

                kneltime += Long.valueOf(
                        Bytes.substring(line, kmtidx, rocidx - 1).trim())
                        .longValue();
                usertime += Long.valueOf(
                        Bytes.substring(line, umtidx, wocidx - 1).trim())
                        .longValue();
            }
            retn[0] = idletime;
            retn[1] = kneltime + usertime;
            return retn;
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                proc.getInputStream().close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /** *//**
     * 测试方法.
     * @param args
     * @throws Exception
     * @author amg     * Creation date: 2008-4-30 - 下午04:47:29
     */
    public static void main(String[] args) throws Exception {
        IMonitorService service = new MonitorServiceImpl();
        MonitorInfoBean monitorInfo = service.getMonitorInfoBean();
        System.out.println("cpu占有率=" + monitorInfo.getCpuRatio());

        System.out.println("可使用内存=" + monitorInfo.getTotalMemory());
        System.out.println("剩余内存=" + monitorInfo.getFreeMemory());
        System.out.println("最大可使用内存=" + monitorInfo.getMaxMemory());

        System.out.println("操作系统=" + monitorInfo.getOsName());
        System.out.println("总的物理内存=" + monitorInfo.getTotalMemorySize() + "kb");
        System.out.println("剩余的物理内存=" + monitorInfo.getFreeMemory() + "kb");
        System.out.println("已使用的物理内存=" + monitorInfo.getUsedMemory() + "kb");
        System.out.println("线程总数=" + monitorInfo.getTotalThread() + "kb");
    }
}

```
该实现类中需要用到一个自己编写byte的工具类，该类的代码如下所示：
```
package com.amgkaka.performance;

/** *//**
 * byte操作类.
 * @author amg * @version 1.0
 * Creation date: 2008-4-30 - 下午04:57:23
 */
public class Bytes {
    /** *//**
     * 由于String.subString对汉字处理存在问题（把一个汉字视为一个字节)，因此在
     * 包含汉字的字符串时存在隐患，现调整如下：
     * @param src 要截取的字符串
     * @param start_idx 开始坐标（包括该坐标)
     * @param end_idx   截止坐标（包括该坐标）
     * @return
     */
    public static String substring(String src, int start_idx, int end_idx){
        byte[] b = src.getBytes();
        String tgt = "";
        for(int i=start_idx; i<=end_idx; i++){
            tgt +=(char)b[i];
        }
        return tgt;
    }
}

package com.amgkaka.performance;

/** *//**
 * byte操作类.
 * @author amg * @version 1.0
 * Creation date: 2008-4-30 - 下午04:57:23
 */
public class Bytes {
    /** *//**
     * 由于String.subString对汉字处理存在问题（把一个汉字视为一个字节)，因此在
     * 包含汉字的字符串时存在隐患，现调整如下：
     * @param src 要截取的字符串
     * @param start_idx 开始坐标（包括该坐标)
     * @param end_idx   截止坐标（包括该坐标）
     * @return
     */
    public static String substring(String src, int start_idx, int end_idx){
        byte[] b = src.getBytes();
        String tgt = "";
        for(int i=start_idx; i<=end_idx; i++){
            tgt +=(char)b[i];
        }
        return tgt;
    }
}

```
运行下MonitorBeanImpl类，读者将会看到当前的内存、cpu利用率等信息
wmic很强大，网上有很多wmic的命令，
eg:wmic 获取物理内存
wmic memlogical get TotalPhysicalMemory
wmic 获取进程信息，很详细
wmic process
System.getProperty("os.name"));//得到操作系统名字
System.getProperty("sun.os.patch.level");//得到操作系统版本


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

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


Instruction:
我想把getData(start)中的使用多个 if 这里优化一下，请问如何处理？
```
async getData(start) {

        const _self = this;
        var response = [];
        if(start == 0){
            try {
                // let response = await fetch('mock-data/selectData01.json').then(function(response) {
                //     return response.json(); // 第1个
                // }).then(function(responseThenData) {
                //     //console.log('responseThenData =',responseThenData);
                //     return responseThenData // 第2个
                // }).catch(function(e) {
                //     console.log("Oops, error");
                // });
                response = await fetch('mock-data/selectData01.json').then(function(response) {
                    return response.json();
                })
                return response; // 第3个
            } catch(e) {
                console.log("Oops, error", e);
            }
        } else if (start == 1) {
            try {
                response = await fetch('mock-data/selectData02.json').then(function(response) {
                    return response.json();
                })
                return response; // 第3个
            } catch(e) {
                console.log("Oops, error", e);
            }
        } else if (start == 2) {
            try {

                response = await fetch('mock-data/selectData03.json').then(function(response) {
                    return response.json();
                })
                return response; // 第3个
            } catch(e) {
                console.log("Oops, error", e);
            }
        } else if (start == 3) {
            try {

                response = await fetch('mock-data/selectData04.json').then(function(response) {
                    return response.json();
                })
                return response; // 第3个
            } catch(e) {
                console.log("Oops, error", e);
            }
        } else if (start == 4) {
            try {

                response = await fetch('mock-data/selectData05.json').then(function(response) {
                    return response.json();
                })
                return response; // 第3个
            } catch(e) {
                console.log("Oops, error", e);
            }
        }
    }

    componentDidMount() {
        const _self = this;
        var key = true;

        let dataReadStart = 0;

        _self.getData(dataReadStart)
            .then(function(responseThenData) {
                //console.log('responseThenData =',responseThenData['dataChinaTelecom']['regionData']);
                _self.setState({
                    tableBody: responseThenData['dataChinaTelecom']['emergencyTableData'],
                    tableHead: responseThenData['dataChinaTelecom']['emergencyTableHeader']
                })
            })
            .then(function() {
                //console.log('abc')
            })
            .catch(function(e) {
                console.log("promise, error =", e);
            });

        // var key = true;
        // new Promise(function(resolve, reject){
        //     if(key){
        //         resolve('成功了')
        //     }else{
        //         reject('被拒绝')
        //     }
        // }).then(function(value) {
        //     console.log(value); // key=true 123
        // }, function (rej) {
        //     console.log('---------result reject');
        //     console.log(rej);
        // })

        dataReadStart = dataReadStart + 1;
        setInterval(function(){

            let dataPromise = _self.getData(dataReadStart);
            console.log('dataPromise =',dataPromise)
            dataPromise
                .then(function(responseThenData) {
                    //console.log('responseThenData =',responseThenData['dataChinaTelecom']['regionData']);
                    _self.setState({
                        tableBody: responseThenData['dataChinaTelecom']['emergencyTableData'],
                        tableHead: responseThenData['dataChinaTelecom']['emergencyTableHeader']
                    })
                })
                .then(function() {
                    //console.log('abc')
                })
                .catch(function(e) {
                    console.log("promise, error =", e);
                });
            if(dataReadStart + 1 == 5){
                dataReadStart = 0;
            } else {
                dataReadStart = dataReadStart +1;
            }

        },30000)

        // ECMAScript 定义了 Undefined、Null、Boolean、String、Number、Object 6种类型
        // 其中 Undefined 和 Null 都是只包含一个值得特殊类型，分别为 undefined 和 null
        // 因此根据定义undefined和null分属不同类型
        // 使用===运算符返回false
        // 当声明的变量未初始化时，该变量的默认值是undefined，而null则用于表示尚未存在的对象
    }

```
这里if能不能缩简到一个

Output:
```
export default class a {
  async getData(start) {
    var response = [];
    const MAP = [
      { url: 'mock-data/selectData01.json' },
      { url: 'mock-data/selectData02.json' },
      { url: 'mock-data/selectData03.json' },
      { url: 'mock-data/selectData04.json' },
      { url: 'mock-data/selectData05.json' },
    ];
    try {
      response = await fetch(MAP[start].url).then(res => res.json());
      return response;
    } catch (e) {
      console.log('Oops, error', e);
    }
  }
}

```
抛砖引玉


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

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


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

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


Instruction:
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;
    }
}
```
放入函数库，怎么放呢

Output:
在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
```


Instruction:
有没有遇到过只在 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)
```


Instruction:
如何写一个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 ，我如何做，才能使用一个脚本，直接实现上面的结果？？？

Output:
直接上代码，自己体会吧。
```
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()
```


Instruction:
对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')` 方法

Output:
## 先回答您的问题
首先，官方这段代码实现的效果，跟您修改后代码的效果是差不多的。
其次，官网这段代码的主要目的，是告诉使用者，`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
```
完。


Instruction:
应该用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;
});
```

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


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

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

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


Instruction:
vscode如何postcss语法并且对其支持emmet和格式化操作
项目使用postcss，嵌套的语法会被vscode报错，有没有什么设置可以忽略掉报错呢……
就像这种，里层的嵌套就会被标红。
```
.pages {
  height: 100%;
  & > div {
    width: 100%;
  }
}
```
本身在css中这样写不行，虽然vsode也不知道我要用postcss编译，报错确实看起来也是合情合理。不过这实在影响查找真的错误（以及强迫症……）……
实在不行还是用回scss算了?

Output:
我是提问者，几天没人回答，终于解决后所以最后自己回答了……。
- vscode支持postcss语法
   安装 `postcss-sugar-language` 这个插件，然后就能在右下角点击格式名称选择PostCss格式了，可使用.postcss .pcss .sss以及.css后缀，我选用了熟悉的css后缀。
-
将css文件视作postcss（为了方便.css文件使用postcss语法不被报错），以及让emmet支持postcss文件。
在settings中的配置：
`"files.associations": {
  "*.css": "postcss"
},
"emmet.includeLanguages": {
  "vue-html": "html",
  "javascript": "javascriptreact",
  "postcss": "css"
}`
另外设置里面不要修改` "emmet.showExpandedAbbreviation": "always",`，默认值就是是always，不过alaways的出发判定机制并不如inMarkupAndStylesheetFilesOnly好，从名字也能看出来:

`"inMarkupAndStylesheetFilesOnly"`，将在 html、haml、jade、slim、xml、xsl、css、scss、sass、less 和 stylus 文件中生效。
 若选择 `"always"`，将在所有适用文件 (不仅仅是标记或 CSS 文件) 的所有部分生效。
但是在该需求要还是不要改这个值，这样就能在postcss中使用emmet的简写（比如dib扩展成display:inline-block），这样就能愉快地在.css后缀）的文件中使用postcss格式(伪装成css的postcss，参看上一条）并且使用emmet啦。

将css文件视作postcss（为了方便.css文件使用postcss语法不被报错），以及让emmet支持postcss文件。
在settings中的配置：
```
`"files.associations": {
  "*.css": "postcss"
},
"emmet.includeLanguages": {
  "vue-html": "html",
  "javascript": "javascriptreact",
  "postcss": "css"
}`
```
另外设置里面不要修改` "emmet.showExpandedAbbreviation": "always",`，默认值就是是always，不过alaways的出发判定机制并不如inMarkupAndStylesheetFilesOnly好，从名字也能看出来:
但是在该需求要还是不要改这个值，这样就能在postcss中使用emmet的简写（比如dib扩展成display:inline-block），这样就能愉快地在.css后缀）的文件中使用postcss格式(伪装成css的postcss，参看上一条）并且使用emmet啦。
以上目的是为了不改变.css文件情况下，自如地切换postcss和css，想写什么前也不用改下后缀，毕竟很多时候我们还是写原生css，同时兼顾使用emmet，这对使用习惯影响很小，唯一不爽就是没法增加`inMarkupAndStylesheetFilesOnly`中的值，加一个postcss多好呀?。
-
postcss文件不能格式化
2019.10.10更新,现在prettier新版又没问题了，直接安装就行啦。
以下就可以不用看了，真香prettier。
——————————————————————————————————————————————————
安装前端都喜欢安装的prettier插件prettier -code formater
最近不能格式化了（版本1.7.1）…… prettier更新后的问题,prettier插件不知从哪个版本起开始抽风，不能格式化css和html，不过默认vscode是可以格式化html的我们只需要禁用prettier对html格式化的接管就行了，在设置中Prettier的disable Languages处修改如下：
` "prettier.disableLanguages": ["vue", "html"]`
或者可以安装prettier1.6.1版，这个版本html格式化没有抽风。
不过可惜的是vscode居然自己不能格式化css（这个就不吐槽了，n版本前就吐槽过），而prettier喵的明明介绍里面写的` format your JavaScript / TypeScript / CSS using Prettier.`，现在连原生css都没法格式化了，要你何用啊，在真香定律作用下，我决定暂时留着这货……安装beautify插件。
机智如我（不要脸），发现在beautify插件配置中可塞进去postcss，直接剥夺prettier对css的接管权限（估计下一步就是将其打入冷宫了，beautify也能格式化json和js呢）在settings的`"beautify.language":`的css数组中添加postcss：
` "prettier.disableLanguages": ["vue", "html", "css"]
 "beautify.language": {
 "css": [
  "css",
  "scss",
  "postcss"
 ],
}`
这个方法最完美啊，还简单。

postcss文件不能格式化
2019.10.10更新,现在prettier新版又没问题了，直接安装就行啦。
以下就可以不用看了，真香prettier。
——————————————————————————————————————————————————
安装前端都喜欢安装的prettier插件prettier -code formater
最近不能格式化了（版本1.7.1）…… prettier更新后的问题,prettier插件不知从哪个版本起开始抽风，不能格式化css和html，不过默认vscode是可以格式化html的我们只需要禁用prettier对html格式化的接管就行了，在设置中Prettier的disable Languages处修改如下：
```
` "prettier.disableLanguages": ["vue", "html"]`
```
或者可以安装prettier1.6.1版，这个版本html格式化没有抽风。
不过可惜的是vscode居然自己不能格式化css（这个就不吐槽了，n版本前就吐槽过），而prettier喵的明明介绍里面写的` format your JavaScript / TypeScript / CSS using Prettier.`，现在连原生css都没法格式化了，要你何用啊，在真香定律作用下，我决定暂时留着这货……安装beautify插件。
机智如我（不要脸），发现在beautify插件配置中可塞进去postcss，直接剥夺prettier对css的接管权限（估计下一步就是将其打入冷宫了，beautify也能格式化json和js呢）在settings的`"beautify.language":`的css数组中添加postcss：
```
` "prettier.disableLanguages": ["vue", "html", "css"]
 "beautify.language": {
 "css": [
  "css",
  "scss",
  "postcss"
 ],
}`
```
这个方法最完美啊，还简单。
另提示：使用`ctrl`-`shift`-`a`进行块注释（即`/* */`），询问过作者，他说后面会把`ctrl`-`/`的注释风格改成`/* */`。


Instruction:
a['b']和a.b，哪个性能更好？
```
var a = {
    b: 9
}

```
如题，a['b']和a.b，哪个性能更好？


Instruction:
在Vue.js中什么是内联处理器？
在文档中 内联处理器中的方法：
请问下`内联处理器`是指的什么呢？

Output:
比较一下这两个写法有什么不同：
## 写法一
```
<div id="example-3">
  <button v-on:click="say">Say hi</button>
  <button v-on:click="say">Say what</button>
</div>
```
```
new Vue({
  el: '#example-3',
  methods: {
    say: function () {
      alert('hello');
    }
  }
});
```
## 写法二
```
<div id="example-3">
  <button v-on:click="say('hi')">Say hi</button>
  <button v-on:click="say('what')">Say what</button>
</div>
```
```
new Vue({
  el: '#example-3',
  methods: {
    say: function (message) {
      alert(message);
    }
  }
});
```
## 差异
一个有括号，一个没括号，对吧？
没括号的这个，直接就是函数名，有括号的这个，实际是一条JS语句，有括号的这个就叫『内联处理器』。
## 没括号的好处
看上去，有括号的更直观，更容易理解。那为什么还要搞什么无括号？
没括号的有这么一个好处：
```
<div id="example-3">
  <button v-on:click="say">Say hi</button>
  <button v-on:click="say">Say what</button>
</div>
```
```
new Vue({
  el: '#example-3',
  methods: {
    say: function (event) {
      alert(event.target.tagName);
    }
  }
});
```
虽然我没括号，但我天生自带`event`参数呀，你在上面不用写`event`，我下面就自带`event`了，你有括号的括号里几个参数，下面就得几个参数，你不能无中生有的。
### 有括号的逆袭
为了让有括号的也能得到无括号娘胎里自带的event参数，我们可以这样写：
```
<div id="example-3">
  <button v-on:click="say('hi', $event)">Say hi</button>
  <button v-on:click="say('what', $event)">Say what</button>
</div>
```
```
new Vue({
  el: '#example-3',
  methods: {
    say: function (message, event) {
      alert(message);
      alert(event.target.tagName);
    }
  }
});
```
送他一个美刀`$`，于是有括号的也可以快乐地使用天然无雕饰的`event`参数了！


Instruction:
函数参数中的中括号究竟代表什么呢？
1.这是我看某文档的时候产生的疑问，如一个node中的write方法：
`buf.write(string[, offset[, length]][, encoding])`
2.问题：函数参数中的中括号代表什么了？怎么有些只有半个括号，比如string[ 或 offset[;而有的却是length]][这样了？
3.还会有其他符号也有它独特代表的含义吗？
4.这种写法的好处是什么？

Output:
以上三个问题作一个问题回答。
简单的回答就是中括号表示这个参数非必须.
接下来详细解释。
首先，这样使用中括号只是出于一种的表达形式的需要而已(这样的表达形式很常见)，这与api本身是没有关系的。
然后，我们拿上面的例子来说
```
buf.write(string[, offset[, length]][, encoding])
```
对于`buf.write`这个方法：
第一个参数`string`是必须的，他表示你要写入的内容；往后的`offset`、`length`、`encoding`这些参数都是非必须的。这些参数你可以不传(用[]括起来表示不传)，但并不表示这三个参数你想怎么传就怎么传的，这里是有规则的，规则从这里中括号的对应关系中可以看出来。我们来看他的对应关系：`[, offset[, length]]` && `[ encoding]`。这表示`offset`、`length`和`encoding`你可以传或者不传,但是你要是没有传`offset`的话那`length`是一定不能传的，这就是为什么`length`要放在`offset`的括号里面的原因。
所以整个例子理解起来就是：
`string`必须传，`offset`、`length`、`encoding`可传可不传，但是`offset`不传的话`length`也不能传。
至于这样写有什么好处，我想这可能是当初写api那帮家伙觉得这样表达更合理吧，后面写文档的觉得这种方式还不错，就依葫芦画瓢了，慢慢的就约定俗成了。


Instruction:
当执行npm publish 时，出现unauthorized 和 is not in the npm registry
当执行npm publish，发生了如下错误：
```
appledeMacBook-Pro:nini-react apple$ npm publish
npm ERR! publish Failed PUT 401
npm ERR! code E401
npm ERR! 404 unauthorized Login first: nini-react
npm ERR! 404
npm ERR! 404  'nini-react' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/apple/.npm/_logs/2018-02-04T00_32_35_475Z-debug.log
appledeMacBook-Pro:nini-react apple$
```
起先以为是账户的问题，我就执行了npm adduser 和 npm login  都不行。公司的电脑都是可以的!哪位大神帮帮忙！

Output:
您首先执行下` npm adduser `，输入您相应的` Username `、` Password `、` Email: (this IS public) `，关键的一步来了!
```
Logged in as 您的Username on https://registry.npmjs.org/.
```
如果` on `后面不是` https://registry.npmjs.org/ `，而是其他的镜像，比如我们大家常见的淘宝镜像：
```
http://registry.npm.taobao.org/
```
那么您首先替换成原来的，替换成原来执行如下命令：
```
npm config set registry https://registry.npmjs.org/
```
最后，替换完毕再执行` npm adduser `、` npm publish `，这样应该就ok了！


Instruction:
请教一道算法题，如下，谢谢！
有一个数组`[1,1,1,2,3,4,5,8,10,22,24,25,26,66]`，
请写一个方法把数组变成`[1,1,[1,2,3,4,5],8,10,22,[24,25,26],66]`
就是把里面连续递增的数字归成一个数组，没思路，有没有好的方案？

Output:
两个指针 i,j
```
var arr = [1,1,1,2,3,4,5,8,10,22,24,25,26,66]
var len = arr.length
var i = 1, j = 0
var rst = []
for(; i <= len; i++) {
  if(arr[i]-arr[i-1] !== 1) {
    i-j===1 ? rst.push(arr[j]) : rst.push(arr.slice(j, i))
    j = i
  }
}
```


Instruction:
php 使用redis进行秒杀的思路
问题大概是这样的,因为项目中设计一个比较简单的类似于秒杀的东西
但几经搜索之后  都说使用redis的原子性  采用队列来处理, 然后去看了一下redis的一些命令
又结合了别人的一些代码   大致思路是以下这样
我有几个问题
1.什么时候触发 左进右出 取数据这个流程呢  ,条件是什么呢
2.还是说     把商品数量提到 检查队列长度之前??
3.或者说我的思路  本身就有很大漏洞或者  歪了
请不留情  斧正
```

    //用户进入
    //获取用户信息
    //连接redis
    //加入队列msList

    //这个位置检查缓存的商品数量??   为0就直接返回了 不用进行下面的操作?

    //检查队列长度
    //--1.大于200就返回  抢购人数过多,跳转抢购结束页面,结束,终止秒杀
    //--2.小于等于就加入队列

    //判断等于200触发下面操作???

    //左进右出  取数据
    //----查询商品数量为num
    //-------1.无则 加入redis缓存
    //-------2.有则判断是否大于0
    //----------1.小于等于就退出 ,跳转库存不足页面,结束
    //----------2.无则判断
    //-------------进入的用户左进右出
    //-----------------事务
    //-----------------1.插入成功,num-1,返回用户消息,结束
    //-----------------1.插入失败,回滚,返回用户消息,结束
    //释放redis

    //订单超时,库存增加??
```

Output: 您可以逆向思考这个秒杀问题，由于Redis的list数据结构是不可能到达“负”长度的，所以可以把需要被秒杀的商品信息和一个唯一编号预先放到指定商品类型的唯一队列中，用户请求时直接lpop出结果，不可能出现超量的问题，很多东西都免了。


Instruction:
js 怎样用正则去掉小数点后面多于的0
想用replace替换掉小数点后面多于的0.
```
例如： 12.000700 ——————> 12.0007

```
注意：若是没有小数点的话，匹配不生效，不替换任何字符。
1.（不希望转为数字）我的整个数值计算是字符串按位计算的，所以我并不希望将他转为数字，而是通过正则的方式去掉多余的0。不愿意转换也有一点是String/Number等方法对小数点后面的位数有限制。
2.（需要考虑没有小数点的情况）/0*$/或者/0+$/这种单纯的匹配末尾是不全面的。可能有没有小数点的存在。
```
并不希望: 12000 ——————> 12

```
这明显改变了数值
3.（目前想到的方法）目前的能想到的用了两个replace一个match。先匹配到小数点右面的字符。再将该字符去末尾0替换到小数点右面。显然不高级，有没有更优雅的写法。
```
var str = "12.000700";
var _tmp = str.match(/\.\d+0+/)[0].replace(/0+$/,'');
console.log(str.replace(/\.\d+0+/, _tmp));
```

Output:
```
const arr=['1200.00100','1200.00000','1200.','1200','1200.10000','0.120010000','0.000011111']
const regexp=/(?:\.0*|(\.\d+?)0+)$/
arr.forEach((item)=>{
    console.log(item.replace(regexp,'$1'))
})

// > 1200.001
// > 1200
// > 1200
// > 1200
// > 1200.1
// > 0.12001
// > 0.000011111
```
再解释下正则的意思`(?:\.0*|(\.\d+?)0+)$`
先分解成4部分

1. `(?:reg1|reg2)` - 它是一个正则分组非捕获组，要么匹配reg1，要么匹配reg2，优先匹配reg1，加上`?:`不对捕获组记录
2. `\\.0*` - 表示匹配一个`.`开头，后边跟着0或0个以上数量的`0`，且不进行捕获，所以在填充`$1`时，就是个空值
3. `(\\.\\d+?)0+` - 它是一个捕获组，匹配一个`.`开头后边跟着非贪婪（懒惰）匹配任意数字，接着在末尾尽可能多的匹配`0`这个字符，匹配完成 后，生成一个捕获组内容
4. `$` - 表示匹配结果需要以`0`作为结尾


Instruction:
一道关于  对象之间  值传递的问题
```
    var a = {
      num: 2
    };

    var b = a;

    a.num = a = {
      num: 4
    };
    console.log(a.num);// 4
    console.log(b.num);// { num: 4 }

```
这个b.num是4不是因为 'var b = a时' b指向a了吗？那为什么下面那个没有指向a
```
    var a = {
      num: 2
    };

    var b = a; //没有把指向给b吗

    a = {
      num: 4
    };
    console.log(b.num)  //为什么是2  a已经是4了b的指向还是a为什么不是4？
```

Output:
Javascript中有5种基础数据类型，分别是`Undefined、Null、Boolean、Number、String（ES6中新加的Symbol，暂时不考虑它）`，基础数据类型都是按值访问，即我们可以直接操作保存在变量中得实际值。而Javascript中的引用数据类型，比如Array，Object。。。它们的值是保存在堆内存中得对象，Javascript 不允许直接访问堆内存中的数据，即无法直接操作对象的堆内存空间。在操作对象时，实际上我们操作的是对象的引用，也就是我们经常提及的内存地址、内存指针等。废话不多说，咱们来看题目。
```
var a = {
  num: 2
};

var b = a;
```
我们通过` var b = a; `进行引用类型的赋值操作，该操作会自动分配一个值保存在变量b，不过这个值就是咱们经常提及的引用类型的一个内存地址或内存指针。当内存地址相同时，尽管变量之间相互独立，但访问的具体对象实际上是同一个，即变量 a 和 b 在内存空间对应的对象是同一个，在该位置您不管是修改a.num，还是修改b.num，它们两个都会受影响！
接下我们再分析一下最容易迷惑的一行代码：
```
a.num = a = {
  num: 4
};
```
因为Javascript的成员访问优先级（19）比赋值优先级（3）高（运算符优先级可参考：运算符优先级），因此先执行成员访问a.num，上面我们说了不管您是修改a.num，还是修改b.num，它们两个都会受影响！所以这里变量b也会受到影响，因此实则发生了如下赋值代码：
```
b.num = a = {
    num: 4
}
```
所以变量b对应的堆内存的对象如下：
```
b = {
 num: {
   num: 4
 }
}
```
接下来我们再看看变量a，变量a起先对应的堆内存的对象为：
```
a = {
  num: 2
};
```
当执行 `b.num = a = { num: 4 }`再次进行引用类型的赋值操作，在这里会重新为a分配一个内存指针！所以a最终变成了：
```
a = {
  num: 4
};
```


Instruction:
怎么在ng4中阻止触摸事件的冒泡or渗透？
我用ng4写了一个触摸滑动组件，部分代码如下：
```
let touchstart = Observable.fromEvent(this.el.nativeElement,'touchstart')
let touchmove = Observable.fromEvent(this.el.nativeElement, 'touchmove')
let touchend = Observable.fromEvent(this.el.nativeElement, 'touchend')

touchstart.map((start:any) => {
  return new Position(start.touches[0].pageX, start.touches[0].pageY)
}).subscribe(start => {
  this.duration = 0;
  this.touchObject.start = start
  transObject.start = new Position(this.trans.x, this.trans.y)
});
```
......
这个组件是fixed在最上层的，他响应触摸滑动的时候，它下面的内容也会跟着一起滑动，有什么办法能够只让它自己滑动呢？

Output:
没试过。试试`Observable`加个`filter`
```
let touchstart = Observable.fromEvent(this.el.nativeElement,'touchstart').pipe(
    filter((evt:any) => evt.target == this.el.nativeElement)
)
```
或者加个`tap`中阻止冒泡试试。
```
let touchstart = Observable.fromEvent(this.el.nativeElement,'touchstart').pipe(
    tap((evt:any) => evt.stopPropagation())
)
```
`Rxjs 5+`


Instruction:
java怎么判断不是常用汉字？例如这类字：挹攀繊昧
java怎么判断不是常用汉字？例如这类字：挹攀繊昧
谢谢！

Output:
把常用汉字做成一个字典存起来，用的时候查就行了
http://blog.csdn.net/mingzzne...
只收录一级汉字的话，也就大约10KB左右的大小
上面的是GB2312标准中的
按新一点的有2013年发布的《通用规范汉字表》，一级字变成了3500个，但是似乎没有整理好的文字版


Instruction:
请问如何修改element表头的样式？浏览器页面不显示出应有的样式
本人萌新，最近在使用element中的表格时遇到了一些问题：
请问在浏览器页面修改该表格中的.el-table th,加入background：#f4f4f4 样式能正常显示，但是在项目的style标签中修改再到浏览器页面就不会显示出应有的样式。
以下是代码：
样式：
```
  .el-table th{
        background:#f4f4f4 !important;
        font-size: large;
    }
```
表格：
```
<el-table
          :data="tableData"
          style="width: 100%"
          border>
          <el-table-column
            prop="doc"
            label="文件名称"
            width="290"
            header-align="center"
          >
          </el-table-column>
          <el-table-column
            prop="name"
            label="发起人"
            width="290"
            header-align="center">
          </el-table-column>
          <el-table-column
            prop="situation"
            label="文件状态"
            width="290"
            header-align="center">
          </el-table-column>
          </el-table>
```

Output:
您说的项目中，应该是指“组件内”吧？
在组件内使用其它组件的时候，有些样式的设置是无效的。
比如你的test.vue中使用了el-table这个组件，但  .el-table th 这个元素在test.vue中并不存在，而是在el-table这个组件内，那么，你在test.vue 中设置  .el-table th的样式是无效的，这应该跟vue的渲染机制有关。
把.el-table th的样式写到全局的css文件中就好了。


Instruction:
求路过前辈指导下小弟学习路线（前端）
```
 小弟前端菜鸟一枚，基础很不扎实，目前断断续续工作了也有半年了，感觉没学到什么东西，反而把知识搞的很乱，现在想自己重新深入学习一遍，由于自己现在东西学的特别乱，十分迷茫，求诸位前辈指点，建议个学习路线，再此写过诸位.
 下面说下我目前会的东西，css,html可以，javascript会用，但不够扎实，css3和html5的东西也差不多可以，bootstrap，jquery，ajax只能说可以简单使用了，还有dojo公司之前也用过，目前正想学习vue看了两天，照着文档可以用，但好多东西根本看不懂。
 真的很是迷乱，求大神指点一条正确学习路线，小弟在此再次写过诸位大神！
```

Output:
我的学习过程经历过及个阶段：主要是从断断续续看书以及实践中升级。或许你可以借鉴一下。
- 阶段0：《jQuery基础教程 (第四版)》
- 阶段1：《JavaScript高级程序设计 (第三版)》
- 阶段3：《JavaScript忍者秘籍》
- 阶段4：《Node.js 实战》《HTTP权威指南》《图解TCP IP》《图解HTTP》`不要以为前端不懂通讯协议也行`

- 阶段5：Vue, Webpack, React (直接在官网按照教程学习)
-
阶段6：自己写一些教程

Vue + Vue-router + Element-ui 搭建一个非常简单的dashboard demo
Vue+ElementUI: 手把手教你做一个audio组件 (ps: 示例音频好好听)

- 阶段7： 开源一些小项目，发布两个npm包

阶段6：自己写一些教程
- Vue + Vue-router + Element-ui 搭建一个非常简单的dashboard demo
- Vue+ElementUI: 手把手教你做一个audio组件 (ps: 示例音频好好听)

我的学习并不是持续的过程，而是断断续续的过程。当然也学到很多其他的东西。当我想学A的时候，我会发现里面有一些有趣的B,C,D可以学习。
总结一下：
- `不要畏惧英文文档，我觉得最好的文档就是官方文档`
- `学习可以不求甚解，渐进式学习`
- `保持对新技术的好奇心，尝试各种新鲜玩意`
- `不要对某个技术特别崇拜`
- `学习要有文档笔记的积累，有个技术博客是不错的加分项`
- 不要认为学好前端就是学好JS, 实际上完全不是如此，你还要掌握HTTP相关知识。例如: OPTIONS预检请求,这里涉及到浏览器的机制，不明白的话，跨域POST时，可能会闹笑话。
- 不要认为前端只是搞前端，有时候后端架构也是要了解的
- ...

另外，编程不是目的。建议阅读以下：`《软技能：代码之外的生存指南》`，`《新生--七年就是一辈子》`。
最重要就是`终身学习，读书，给自己打补丁，升级自己的操作系统。`


Instruction:
用better-scroll做的轮播图,为什么不能无缝循环?
一.实锤:
1.1 html:
```
  <div class="slider" ref="slider">
    <div class="slider-group" ref="sliderGroup">
      <div v-for="item in recommends">
        <a :href="item.linkUrl">
          <img class="needsclick" @load="loadImage" :src="item.picUrl">
        </a>
    </div>
    <div class="dots">
      <span class="dot" :class="{active: currentPageIndex === index }" v-for="(item, index) in dots"></span>
    </div>
  </div>
```
1.2 script:
```

<script>
import BScroll from 'better-scroll'
import {addClass} from 'common/js/dom'
export default{
  props: {
    loop: {
      type: Boolean,
      default: true
    },
    autoPlay: {
      type: Boolean,
      default: true
    },
    interval: {
      type: Number,
      default: 4000
    }
  },
  data() {
    return {
      dots: [],
      currentPageIndex: 0
    }
  },
  mounted() {
    setTimeout(() => {
      this._setSliderWidth()
      this._initSlider()
      this._initDots()

      if (this.autoPlay) {
        this._play()
      }
    }, 20)

    window.addEventListener('resize', () => {
      if (!this.slider) {
        return
      }
      this._setSliderWidth(true)
      this.slider.refresh()
    })
  },
  methods: {
    _setSliderWidth(isResize) {
      // 取轮播组的子元素
      this.children = this.$refs.sliderGroup.children

      let width = 0
      // 取轮播组件宽度(即屏幕宽度)
      let sliderWidth = this.$refs.slider.clientWidth
      for (var i = 0; i < this.children.length; i++) {
        let child = this.children[i]
        addClass(child, 'slider-item')

        // 设置轮播子图宽度为屏幕宽度
        child.style.width = sliderWidth + 'px'
        // 将轮播子图累加
        width += sliderWidth
      }

      // ???
      if (this.loop && !isResize) {
        width += 2 * sliderWidth
      }
      this.$refs.sliderGroup.style.width = width + 'px'
    },
    _initSlider() {
      this.slider = new BScroll(this.$refs.slider, {
        scrollX: true,
        scrollY: false,
        momentum: false,
        snap: true,
        snapLoop: this.loop, // 循环
        snapThreshold: 0.3,
        snapSpeed: 400,
        click: true
      })

      this.slider.on('scrollEnd', () => {
        let pageIndex = this.slider.getCurrentPage().pageX
        if (this.loop) {
          pageIndex -= 1
        }
        this.currentPageIndex = pageIndex

        if (this.autoPlay) {
          clearTimeout(this.timer)
          this._play()
        }
      })
    },
    _initDots() {
      this.dots = new Array(this.children.length)
    },
    _play() {
      let pageIndex = this.currentPageIndex + 1
      if (this.loop) {
        pageIndex += 1
      }
      this.timer = setTimeout(() => {
        this.slider.goToPage(pageIndex, 0, 400)
      }, this.interval)
    }
  }
}
</script>
```
二.线索:
1. 可以轮播,但不能循环(不能从第一张往前翻,不能从最后一张往后翻)
2. 按教程里给slider-group增加了2个slider的宽 度(是为无缝循环准备的?),但他们出现在轮播图片的末尾(2个空白)
3. 第一张图没有对应dot,第二张图对应第一个dot,以此类推
4.  对比了教程里的代码,几乎没有区别,数据来源也是一样,替换了代码也是这样的表现,so百思不得其解

Output:
新版本已经更新了，是版本的问题,在0.1.15版本这么写是没问题的,snap的各个配置项并列写,但在新版本要写在一个snap对象内
_initSlider() {
```
let slider = new BScroll(this.slider, {
  click: true,
  scrollX: true,
  scrollY: false,
  momentum: false,
  snap: {
    loop: true,
    threshold: 0.3,
    speed: 400
  },
})

这么写就可以了
```

另外还有几个小修改,请您作为参考
`
```
    _initDots() {
      // this.dots = new Array(this.children.length) // 原写法
      this.dots = new Array(this.children.length - 2)
    },
```
2.升版本,修改创建better-scroll的配置时,dot与图片不对应:
```
  // bs对象配置方法中(配置后):
  this.slider.on('scrollEnd', () => {
        let pageIndex = this.slider.getCurrentPage().pageX
        // 老版本有,新版去掉:
        // if (this.loop) {
        //   pageIndex -= 1
        // }
        this.currentPageIndex = pageIndex

        if (this.autoPlay) {
          clearTimeout(this.timer)
          this._play()
        }
      })
```


Instruction:
JavaScript数组map方法的疑问[已解决]
问题
一个长度为4空数组
用`map()`给数组元素赋值
为什么新数组还是空的呢?
下面的代码为什么不输出
`[empty × 4]     　　 [2,2,2,2]`
代码
```
var array = new Array(4);
var newArray = array.map(item=>{
    return '2'
});
console.log(array,newArray);
// =>[empty × 4]　　　[empty × 4]
```
解决

Output:
什么都没有的数组元素叫做槽(slot)，一般方法都会忽略，可以用 `Array.prototype.fill`、`Array.from` 或者 `[...arr]` 的方式转换。
比如 `Array.from(new Array(4))`


Instruction:
vue单页面引入cdn
vue单页面应用中需要引入百度地图的三个cdn文件来画图
但是网上都说在index.html加，这样的话会有不必要的加载影响速度，
所以想问怎么只在单个组件里引入这三个文件

Output:
封装一个工具函数，比如bmap.js，大致代码如下：
```
export function MP() {
  return new Promise(function (resolve, reject) {
    window.onload = function () {
      resolve(BMap)
    }
    let script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'http://api.map.baidu.com/api?v=2.0&ak=ak&callback=init';
    script.onerror = reject;
    document.head.appendChild(script);
  })
}
```
组件中使用：
```
import { MP } from './bmap.js'
export default {
    mounted() {
       this.$nextTick(function() {
          const _this = this;
          MP().then(BMap => {
              // 其他操作
          })
        })
    }
}
```


Instruction:
问一个数据库乐观锁的问题
通常我们采用引入一个version版本号来作为乐观锁，提交的时候校验这个版本号，那么此时有两种方式
方式一，程序中对版本加一，即判断条件为数据库版本小于当前传入的版本：
update set name = ${name} and version = ${version} where id = ${id} and version < ${version}
方式二，通过数据库进行加一，即判断条件为数据库版本等于当前传入的版本：
update set name = ${name} and version = version + 1 where id = ${id} and version = ${version}
请问下，这两种方式有什么不同吗，因为我看几乎所有的乐观锁都是用第二种方式来实现的

Output:
结果是一样的，方法二比较好理解点罢了。
很多情况下，乐观锁并不需要version，比如你要UPDATE的是name这一列，那就可以把name当成version，这样就可以写成：
```
UPDATE ... SET name = ${newname} WHERE id = ${id} AND name = ${oldname}

```
我也不知道用方法一该怎么来写呢。


Instruction:
用JS怎样才能正确的得到字符串的长度？
```
var s = '吉林?';
s.length; //4
```
用js输出s.length的是4，但是变量s的字符串的个数是3，如何通过代码准确得到变量 s 的字符串个数（3）？

Output:
`s.match(/[\s\S]/gu).length`
主要是正则表达式`u`标志符可以匹配4字节 Unicode 编码。
空字符串要处理一下。。。因为 match 返回 `null`。
正则表达式`u`是ES6的特性，同样的ES6的字符串迭代器也能正确处理 Unicode 编码：`[...s].length`等等写法。
我好奇地跑去 babel 测试了一下，发现了这群大触丧病的 hack：
```
s.match(/[\s\S]/gu)

s.match(/(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g)
```


Instruction:
JS如何优雅的创建连续元素的数组？
RT, 仅供娱乐，不喜勿喷。
下边是常规的实现方式
```
function ls(count) {
    var a = [], b = 1;
    for (; b <= count; b++)
        a.push(b);
    return a;
}

ls(6);  // [1, 2, 3, 4, 5, 6]
```

Output:
```
Array.apply(Array, Array(20)).map((v, k) => k)
```
```
[...Array(20)].map((v, k) => k)
```
```
' '.repeat(20).split('').map((v, k) => k)
```
```
Array.from({ length: 20 }).map((v, k) => k)
```
```
Array.from(function* gen(i, l) {
      while(i < l) yield i++;
}(0, 20));
```
```
Object.keys([...Array(20)]) // 字符串
```


Instruction:
小白提问：python 在什么时候用函数，什么时候用类？
半路自学的编程小透明，刚刚接触python这门语言。现在有个疑问想请教大家。
我想问的是，大家是如何判断、以及用什么标准来决定什么时候使用函数？什么时候使用类？
函数还好说，一段代码需要重复使用的时候用函数会减少代码量。
但是我遇到了这样一个实例，由于目前思想上更习惯使用面向过程编程，所以在编写下面这个小小爬虫程序的时候就写成了这样的形式：
```
# 任务目标是爬取特定网页上图片列表页面的所有图片。
# 由于是列表页面所以有一个总页数，就使用了 for 循环遍历所有页面，然后下载个页面图片的思路。
# 大致如下

base_url = 'xxx/page='    # 网址忽略了
pages = 90                # 假设一共有 90 页

for page in range(1, pages + 1):          # 首先使用 for 遍历列表的每一页，获取所有的 img 标签
    url = base_url + str(page)
    rq = requests.get(url)
    soup = BeautifulSoup(rq.text)
    all_tag_img = soup.find_all('img')

    for tag in all_tag_img:              # 然后在通过 for 遍历所有标签获取下载地址，下载后保存
        img_url = tag.get('src')
        img = requests.get(img_url)
        # 下面就是获取图片的名称，然后保存什么的了

```
这样下来的话，流程上面感觉比较接近普通浏览的顺序，
但这是这里用不到函数，更用不到类，但是见到过很多爬虫教程，大家会把例如下载图片、获取名称、保存这些东西封装成函数。有些直接就是创建一个爬虫的类，然后增加各种功能。
所有，问题就是，这样一个任务，你们回去用函数或类么？为什么？
我觉得编程最难的是思想，所有我特别想知道你们是怎么考虑的
万分感谢

Output:
个人觉得，其实这个跟你需要完成的任务有关。打个比方，你只是自己想写一个程序，方便自己工作，那你就可以写函数为主，反正自己知道这些函数什么意思，有时候换地方使用直接copy一下，修修改改就好了。
而如果是完成某个大的项目，项目要分很多块，那么就必须写类了。有人说我写个函数，最终实现起来还不是一样？实现起来是一样，那么后期维护呢？你是更喜欢看一个模块，这个模块有几个类，还是说喜欢看几十个函数呢？显而易见，一般稍微有点样子的项目都是分成几个模块，每个模块会分出几个类来各自实现某个特定的任务。到代码层的时候，才会需要看函数的代码。
如果一个项目是由按照某些顺序，直接调用几十个函数完成的，相信后期维护的人会疯吧？好气啊，全是函数，虽然有说明，也很费事的吧？


Instruction:
Laravel 5.5 中该怎么拦截表单校验失败重定向或者返回JSON的返回格式？
在 laravel 5.1 中 可以在 BaseController 中重写
```
/**
     * {@inheritdoc}
     */
    protected function buildFailedValidationResponse(Request $request, array $errors)
    {
         return new JsonResponse($errors);
    }
```
可以实现拦截`$this->validate($request,$rules,$messages);`方法的自动跳转
现在在 laravel 5.5 中没有了这个方法，现在该怎么修改？

Output:
我自己回答这个问题吧，希望以后那些自己不能提出解决方案只会说教别人的嘴炮都闭嘴吧。
一. 仍然使用 控制器 中的`$request->validate($rules);`进行校验，在表单输入不合法的时候，会抛出一个`throw new ValidationException();`错误，可以在`App\Exceptions\Handler`的 `render()`方法中去捕获它
```
        if ($exception instanceof ValidationException) {
                    return new JsonResponse($exception->getMessage());
                }
```
二. 我们不使用 request 对象中的 validate 方法，自己构造一个验证
```
        $validator = Validator::make($request->all(), $rules);
        if ($validator->fails()) {
            return new JsonResponse($validator->getMessage());
        }
```
推荐使用第一个解决方案，仍然可以达到之前的效果，代码修改量也最小。


Instruction:
vue element tab切换两个表格，第一次点切换进来，表格渲染会闪一下，这是什么原因？
vue element tab切换两个表格，第一次点切换进来，表格渲染会闪一下
```
      <el-tabs v-model="activeName">
            <el-tab-pane label="实物" name="first">
                <!--实物表格-->
                <el-table :data="tableData1" border style="width: 100%"  ref="multipleTable" @selection-change="handleSelectionChange">
                    <el-table-column prop="ordergoods" label="活动订单商品" align="center"></el-table-column>
                    <el-table-column prop="consignee" label="收货人信息"></el-table-column>
                    <el-table-column prop="buyeraccount" label="下单人账号" width="150" align="center"></el-table-column>
                </el-table>
            </el-tab-pane>
            <el-tab-pane label="虚拟" name="second">
                <!--虚拟表格-->
                <el-table :data="tableData2" border style="width: 100%" ref="multipleTable" >
                    <el-table-column prop="virtualOrderGoods" label="活动订单商品" align="center"></el-table-column>
                    <el-table-column prop="activationCode" label="激活码" align="center"></el-table-column>
                    <el-table-column prop="validityTerm" label="有效期" align="center"></el-table-column>
                    <el-table-column prop="buyerAccount" label="下单人账号" align="center"></el-table-column>
                    <el-table-column prop="state" label="状态" align="center"></el-table-column>
                </el-table>
            </el-tab-pane>
        </el-tabs>
```
之后再点击切换就是正常的，刷新页面第一次进来的时候会闪

Output:
使用`v-if`控制`el-tab-pane`里的内容是可以的，亲测有效
例如`v-if="activeName === 'second'"`
例子详见
https://jsfiddle.net/athena03...


Instruction:
python写爬虫较node和PHP有什么优势？
## 问题
-
python 写爬虫较php有什么优势？
python和php的话，都简单易学。python其实内置类型实现上更优雅（都面向对象了），别的有什么优势嘛？
-
python 写爬虫较node有什么优势？
node模拟js环境方便点，python能做到多线程，别的有什么优势嘛？

Output:
都是 `图灵完备` 的语言，不存在什么这语言能做，那语言不能做这种问题，顶多就是实现其实复杂不复杂。
你说的几种语言都有一些良好的抓取库。
Python 爬虫的优势就是
1、名气大，大家都知道
2、大家都是用，贡献代码
以上 2 点良性循环。
难道爬个简单的网页，PHP ，Node 做不到么。


Instruction:
H5商城项目里关于价格运算是由前端来做还是后端来做？
公众号里的h5商城项目，比如买下选择了三个糖果，点立即购买跳到结算页，结算页有个“合计”多少钱，像这种运算都是把商品价格和数量传给后端再从后端拿到，还是前端自己算出来？不过js浮点运算有精度问题，是都交给后端来算吧？

Output:
其实这个问题根本就不用问，因为必须后端算 。并且过程是这样的 。
1、后台加载订单或者商品，这里订单的总价可以是前端算，但是注意精度。
2、当有代金券或者优惠券等减少金额的也可以在前端算 。但是只是提供展示。
3、订单提交，把订单中的商品信息带过去，包括订单金额、优惠券之类都提交过去。
4、后端接到信息后，应该根据订单中有的商品，重新查数据库得到准确的价格，重新计算然后如果有代金券要校验代金券的真实性和有效性，然后再计算总价。这个总价是有意义的，决定着最后支付的金额多少。
5、有人肯定会问、那前端的总金额提交后台有什么用？可以做一个对比，如果计算的结果和前端的总价有区别，那证明这个订单有问题 。要么是页面没刷新，导致商品价格、代金券之类有偏差，可以直接返回到对应的提示页面，告诉用户刷新重新提交订单。另外有可能信息被篡改，那同样的处理，如果是0.01这种，需要记录日志做对应的处理惩罚或者预防 。
手机打字不容易，有帮助请采纳和点赞。?


Instruction:
前后端分离项目，你们是怎么控制权限的？
已经做前后端分离 快一年了
技术栈趋向成熟
- vue
- vue router
- vuex
- node
- express
做出来的是单页面应用，但是在权限上一直都有问题。
现在我做权限 是 后台有一套，前端又有重复的一套，麻烦就在这里，
- 只有我对后台有请求的时候，我才知道用户到底有没有这个权限「因为前台的权限，就存在 localSorage 里面，用户可以更改」，如果请求发现没权限，还是前端 router 跳到没权限或者登录页，但是如果这个页面没有请求呢。
-
因为是一个管理系统，权限特别细，比如某些用户只有这几个目录可以看，其他用户只有那几个目录可以看，但我用的是前端路由，问题又来了。

前端路由一般都是配置好的，我怎么让用户一进来就跳到他自己有权限的页面的第一页。
如果用户直接输入 一个没有权限进入的地址 我该怎么拦截「须知我的拦截其实没有意义，因为页面都在他那里，他只需要改掉我的拦截代码就行」

因为是一个管理系统，权限特别细，比如某些用户只有这几个目录可以看，其他用户只有那几个目录可以看，但我用的是前端路由，问题又来了。
- 前端路由一般都是配置好的，我怎么让用户一进来就跳到他自己有权限的页面的第一页。
- 如果用户直接输入 一个没有权限进入的地址 我该怎么拦截「须知我的拦截其实没有意义，因为页面都在他那里，他只需要改掉我的拦截代码就行」
这里 我现在的解决方案是
- 还是后台传给我 详细的权限，用于我铺设页面，如果这个没有权限，导航上也是没有显示的，但是这样还是可以被更改。
-
第二个 用户登录 就会跳他能看到页面的第一个。

首先 路由上 是全部都注册好的
请求之后拿到权限，然后根据权限 生成导航数组
然后自动页面跳到导航数组的 第一个
切换页面的时候，都要去根据导航数组判断他是否有这个页面权限。

第二个 用户登录 就会跳他能看到页面的第一个。
- 首先 路由上 是全部都注册好的
- 请求之后拿到权限，然后根据权限 生成导航数组
- 然后自动页面跳到导航数组的 第一个
- 切换页面的时候，都要去根据导航数组判断他是否有这个页面权限。
但是我觉得自己的办法太笨拙，而且还是会被篡改，所以求解答疑惑，谢谢了。

Output:
我觉得您的问题应该是不存在的。
后端做了权限控制，无权看到的内容就不会返回了，即使你请求了这个接口。
前端也控制了权限，无权访问的页面，导航中就不会显示了，如果用户自己在前端修改了前端的数据，或者跳过你给的导航，直接通过url访问对应的页面，也应该不会有什么大问题，因为即使他能在前端访问到那个页面，但每个页面都有对应的内容（数据），显示内容的时候是需要请求后端的，后端没有权限，打开页面也只能是空白。
你只要后端做好了权限控制，前端无论怎么改也应该是不能获取到自己没有权限的内容的。
从数据安全的角度来说，前端可以完全不使用权限控制；如果你那里做不到这点的话，那么，你后端的权限控制肯定是有问题的。
前端的权限控制只是为了给用户更好的体检；并不是真的拿来控制权限的。


Instruction:
报错！Cannot assign to read only property 'exports' of object
```
export default {
    data(){
        return {
            currentPage: 'findMusic',
            currentCut: 'discover',
        }
    },
    name: 'home',
    components: {
        headTop
    },
    mounted(){
         new Swiper('.swiper-container', {
            loop: true,
            autoplay: 3000,
            autoHeight: true,
            grabCursor: true,
            prevButton: '.swiper-button-prev',
            nextButton: '.swiper-button-next',
            pagination: '.swiper-pagination',
        });
    }
}
```
```
import '../plugins/swiper-3.4.2.min.js'
import '../styles/swiper.min.css'
```
```
<div class='swiper-container'>
            <div class='swiper-wrapper'>
                <div class='swiper-slide'><img src='../assets/slide/slide1.jpg'/></div>
                <div class='swiper-slide'><img src='../assets/slide/slide2.jpg'/></div>
                <div class='swiper-slide'><img src='../assets/slide/slide3.jpg'/></div>
                <div class='swiper-slide'><img src='../assets/slide/slide4.jpg'/></div>
                <div class='swiper-slide'><img src='../assets/slide/slide5.jpg'/></div>
                <div class='swiper-slide'><img src='../assets/slide/slide6.jpg'/></div>
            </div>
            <div class='swiper-pagination'></div>
            <div class='swiper-button-prev swiper-prev'></div>
            <div class='swiper-button-next swiper-next'></div>
        </div>
```
网上搜索，说的是 import 和 module.export不能混用，可是我这里没有混用啊。。。晕，麻烦简单直接地回答一下就行

Output:
需要引入插件 babel-plugin-transform-es2015-modules-commonjs
然后在 .babelrc中配置 { "plugins": ["transform-es2015-modules-commonjs"] }


Instruction:
python的for循环同时遍历两个list?
```
b = [1, 2, 3]
c = [(10, 20), (30, 40), (50, 60)]

for i, j in b, c:
    print(i, j)

```
```
ValueError: too many values to unpack (expected 2)
```
```
b = [1, 2]
c = [(10, 20), (30, 40)]

for i, j in b, c:
    print(j)
```
```
2
(30, 40)
```
这输出到底是怎么回事啊, 不能这么遍历吗...
为什么我印象中有这种用法呢...
`dict.items()` 就能用:
```
for key, value in x.items()
```
遍历..

Output:
當你寫出 `b, c` 的時候, Python 會以為你要製造一個 tuple, 所以:
```
for i, j in b, c:
```
相當於:
```
for i, j in (b, c):
```
當 `b = [1, 2, 3]` 且 `c = [(10, 20), (30, 40), (50, 60)]` 時就相當於:
```
for i, j in ([1, 2, 3], [(10, 20), (30, 40), (50, 60)]):
```
所以第一個迭代到的對象是 `[1, 2, 3]`, 而這個 list 有三個元素自然是無法拆解成兩個變量 `i` 和 `j` 的。
但如果 `b = [1, 2]` 且 `c = [(10, 20), (30, 40)]`，則相當於:
```
for i, j in ([1, 2], [(10, 20), (30, 40)]):
```
第一個迭代到的對象是 `[1, 2]`, 該 list 有兩個元素恰能 unpack 為 `i` 和 `j`，所以下面的語法是能夠順利運行的。
回到你的需求，若要平行迭代兩個 list，你需要的是 `zip` 或 `zip_longest`，你可以參考 @Python爬虫分享 的範例。
我回答過的問題: Python-QA


Instruction:
gulp和webpack究竟有什么区别？
我学了这两款工具之后，发现他们做的事情基本上都是一样的啊，比如说整合好几个js文件（模块）成一个文件，然后进行压缩和检查语法，或者调用bable和sass编译器把他们编译成浏览器可以用的文件，包括gulp的watch在webpack里面也有插件可以实现这个功能，那么他们区别究竟是什么呢？
我百度了半天，很多人只是从用法上说了他们的区别，webpack是写好配置文件，然后webpack自己按照配置文件来执行前端构建流程，而gulp是直接自己写流程，就像linux下写sh那样，那么这只是用法上的区别，从他们的执行结果和功能来看我看不出啥区别啊。。。

Output:
Gulp 的定位是 Task Runner, 就是用来跑一个一个任务的。
放在以前比如我想用sass写css, coffee写js, 我必须手动的用相应的compiler去编译各自的文件，然后各自minify。这时候designer给你了两张新图片，好嘞，接着用自己的小工具手动去压缩图片。
后来前端人不能忍了，搞出个自动化这个流程的 Grunt/Gulp, 比如你写完代码后要想发布production版本，用一句 `gulp build` 就可以
1. `rm` 掉 dist文件夹中以前的旧文件
2. 自动把sass编译成css, coffee编译成js
3. 压缩各自的文件，压缩图片，生成图片sprite
4. 拷贝minified/uglified 文件到 dist 文件夹

但是它没发解决的是 js module 的问题，是你写代码时候如何组织代码结构的问题.
之前大家可以用 require.js, sea.js 来 require dependency, 后来出了一个 webpack 说 我们能不能把所有的文件(css, image, js) 都用 js 来 生成依赖，最后生成一个bundle呢？  所以webpack 也叫做file bundler.

同时 webpack 为了解决可以 require 不同文件的需求引入了loader, 比如面对sass文件有
1. sass-loader, 把sass 转换成 css
2. css-loader, 让 webpack 能识别处理 css
3. style-loader, 把识别后的 css 插入到 html style中
类似的识别es6 有babel-loader

本来这就是 webpack 的初衷，require everything, bundle everything. 一开始 webpack 刚出来的时候大家都是把它结合着 gulp 一起用的， gulp 里面有个 gulp-webpack，就是让 webpack 专门去做module dependency的事情, 生成一个bundle.js文件，然后再用 gulp 去做一些其他杂七杂八minify, uglify的事情。 后来人们发现 webpack 有个plugins的选项， 可以用来进一步处理经过loader 生成的bundle.js，于是有人写了对应的插件， 所以minify/uglify, 生成hash的工作也可以转移到webpack本身了，挤掉了gulp这部分的市场份额。 再后来大家有发现 npm/package.json 里面的scripts 原来好好用啊，调用任务的时候就直接写一个简单的命令，因为 gulp 也不就是各种插件命令的组合呀，大部分情况下越来越不需要 gulp/grunt 之类的了 ref. 所以你现在看到的很多新项目都是package.json里面scripts 写了一堆，外部只需要一个webpack就够了。

打个不恰当的比方，webpack就像微信一样，本来就是做聊天(module dependency)的，后来生生搞出一个微信小程序(processing files)，大家面对简单的需求发现这个比原生app方便使用啊，于是开发原生的人越来越少一样。

所以 LZ 一开始就模仿其他项目用 npm scripts + webpack 就好了，当你发现有哪些任务你没法用 webpack 或者npm scripts 解决起来麻烦， 这个时候再引入task runner 也不迟


Instruction:
vue项目如何引入babel-polyfill
babel-pollyfill 官方说的是：
```
With webpack.config.js, add babel-polyfill to your entry array:
```
```
With webpack.config.js, add babel-polyfill to your entry array:
module.exports = {
  entry: ["babel-polyfill", "./app/js"]
};
```
但是项目没有webpack.config.js， 倒是有 build/webpack.base.conf.js。 但是里面的结构为：
```
module.exports = {
  entry: {
    app: './src/main.js'
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  }
...
```
entry: ["babel-polyfill", "./app/js"]  该怎么加进去呢？

Output:
main.js 里面引入
```
import 'babel-polyfill'
```
webpack.base.conf.js 替换到entry部分
```
  entry: {
    // app: './src/main.js'
    app: ["babel-polyfill", "./src/main.js"]
  },
```
注意：多试一下，清空缓存，多试试，我也是捣鼓捣鼓才可以的


Instruction:
vue组件created中创建的setInterval定时器，离开页面之后仍然在执行，怎么让它停止下来，等下次进来的时候再执行？
如果离开页面还在执行，那么以后每次点击进来岂不是都会重新执行setInterval创建一个定时器？

Output:
解决办法如下：
```
data: {
    return {
        timer: null
    }
},
created() {
    this.timer = setInterval(....);
},
beforeDestroy() {
    if(this.timer) { //如果定时器还在运行 或者直接关闭，不用判断
        clearInterval(this.timer); //关闭
    }
}
```


Instruction:
iView中Table通过render添加一个Input如何双向绑定数据
有一个Table：
```
<Table :columns="columns" :data="data" :border="true"></Table>
```
JS代码如下：
```
 export default {
        data(){
            return {
                columns:[],
                data:[{name:11111,name2:'加工精度',value:'',key:''}]
            }
        },
        created(){
            this.init();
        },
        methods:{
            init(){
                let vm = this;
                this.columns = [
                    {
                        title: '序号',
                        key: 'name'
                    },
                    {
                        title: '检验项名称',
                        key: 'name2'
                    },
                    {
                        title: '检验值',
                        key:'value',
                        render: (h, params) => {
                            return h('Input',{
                                props:{
                                    type:'text',
                                    value:vm.data[params.index].value //此处如何让数据双向绑定
                                },
                                on:{
                                    'on-change':(event) => {
                                        console.log(params)
                                    }
                                }
                            })
                        }
                    },
                    {
                        title: '检验结论',
                        key:'key',
                        render: (h, params) => {
                            return h('Select',[
                                h('Option', {
                                    props: {
                                        value: '1',
                                    }
                                }, '合格'),
                                h('Option', {
                                    props: {
                                        value: '2',
                                    }
                                }, '不合格')
                            ]);
                        }
                    },
                ]
            },
            get(){
                console.log(this.data)
            }
        }
    }
```

Output:
```
render: (h, params) => {
                            return h('Input',{
                                props:{
                                    type:'text',
                                    value:vm.data[params.index].value
                                },
                                on:{
                                    'on-blur':(event) => {
                                        vm.data[params.index].value = event.target.value;
                                    }
                                },
                            })
                        }
```
通过这个方法可以解决


Instruction:
vue watch怎样同时监听两个值的变化并执行方法？
```
watch:{
      city(cur,old){
          this.loadTop();
      },
      country(cur,old){
//        this.loadTop();
      },
    }
```
如上，我想在城市和国家都变化的时候执行刷新的方法，而不是单一执行刷新

Output:
用computed定义一个address对象吧，然后再去watch addres
```
data() {
  return {
    city: '',
    country: ''
  }
},
computed: {
  address() {
    const { city, country } = this
    return {
      city,
      country
    }
  }
},
watch: {
  address: {
    handler: function(val) {
      console.log('address change: ', val)
    },
    deep: true
  }
}

```
只的在computed里面调用也行，不过要使用$nextTick，不然值会是更新前的值。
```
data() {
  return {
    city: '',
    country: ''
  }
},
computed: {
  address() {
    const { city, country } = this
    this.$nextTick(() => {
      console.log(this.city, this.country, 3333)
    })
    return {
      city,
      country
    }
  }
},
```


Instruction:
vue怎么在beforeCreate里获取data
被问的一个面试题：vue怎么在beforeCreate里获取data


Instruction:
redis连接池问题
比如就一个服务A，部署在服务器1上。
redis部署在服务器2上。

为什么还会需要redis连接池这个东西？我在服务A上维护一个全局变量的redis连接实例，前端请求过来我都是用这个连接实例去执行redis指令，不也可以吗？

 redis连接池，无非就是高并发的时候可以支持多个redis连接实例去连接redis，但是redis本身就是单线程的，我多个连接同时去连redis（不还是得排队么），然后执行指令，和我单个全局连接直接去一个个执行redis指令，感觉应该差不多性能吧？

而且如果是全局单个redis连接的话，每次请求过来我还省了连接这个操作，不是又省了点时间么？

Output:
您的说法并不正确。

1. redis本身是单线程的没有问题，但这并不表示，使用连接池不能提供效率，只是不能通过多线程提高效率而已。
2. redis连接池较单链接的效能提高很多。要了解为什么redis连接池能够这么大幅的提高性能，就要了解单链接的性能瓶颈在哪。
单线程并 不是redis性能瓶颈。对redis而言，有两个性能所在（一个是计算性能，也就是所谓的执行命令速度，另一个是网络通信性能）。很显然，redis较执行效率而言，通信才是其瓶颈。据我所知（不一定正确，但也相差无几），redis执行命令大概是10w/s，因此，对于客户端 将若干条（若干条显然不会很大）命令传输给redis服务，命令执行时间和通信时间比等于0.(假设以1s举例，几条命令传输时间为40ms, 而每秒可执行10w个命令，即n/10w 秒就可执行完毕，等待下一个命令到来的时间间隙(约39ms多)redis没有任何命令执行)，这就造成了redis闲置。
综上，要提高redis的性能，可以降低单位时间内的通信成本。那么连接池就是一个不错的选择。
客户端使用连接池+多线程方案，使得使得redis服务闲置时间降低，极大地提高了服务效率。


Instruction:
return 对代码可读性的影响
在函数中，是否应该控制尽量少的 `return` 出口？
比如 （以 `PHP` 代码举例）：
```
<?php

/**
 * 控制尽量少的退出点
 */
function foo1($var)
{
    try {
        if (empty($var)) {
            throw new \Exception('emty var');
        }

        if (!is_string($var)) {
            throw new \Exception('var must be string');
        }

        return sprintf("input-var:%s \n", $var);
    } catch (\Exception $e) {
        return sprintf("error:%s \n", $e->getMessage());
    }
}

/**
 * 不控制，可以结束的时候直接 return
 */
function foo2($var)
{
    if (empty($var)) {
        return 'error:empty var' . PHP_EOL;
    }

    if (!is_string($var)) {
        return 'error:var must be string' . PHP_EOL;
    }

    return sprintf("input-var:%s \n", $var);
}

```
### 常见观点
#### 正面：应该控制
- 过多的 `renturn`，增加了函数出口点，不利于代码阅读
#### 反面：没必要
- 多个 `return` 也没什么，类似 `try-catch` 在效率上有所损失，尽量少用
#### 中立
- 两种写法只是跟人风格问题，没有优略
- 短函数多个 `return` 无伤大雅，但是长函数中，会严重降低可读性
欢迎留下你的观点。
我的观点：
无论是短函数还是长函数，都尽量控制一下 `return` 点，因为短函数随着迭代可能会变成长函数。
而且多个 `return` 会明显降低长函数的可读性。
对于 `try-catch` 结构，在性能上的一丁点牺牲，换来的可读性提升，是值得的。

Output:
观点与你相反，函数中要尽可能多的使用 return 来控制，因为 return 从设计上来说就是这个功能，表示执行权限的移交。这样不会造成任何执行权限的问题。所谓函数，从设计之初，核心就是计算和返回。
滥用 try catch 会导致上级 try catch 无法正确捕获异常
语义化上来说，return 也比 try catch 更加清晰明了。


Instruction:
@Service是标记在接口上还是实现类上？
@Service是标记在接口上还是实现类上？

Output: `@Service`注解是标注在实现类上的，因为`@Service`是把`spring`容器中的`bean`进行实例化，也就是等同于`new`操作，只有`实现类`是可以进行`new`实例化的，而`接口`则不能，所以是加在`实现类`上的。


Instruction:
webpack(config,function(){}) , 这个函数的第二个参数有什么作用？
```
var webpack = require('webpack')
var webpackConfig = require('./webpack.config.js')

webpack(webpackConfig, function(err, stats) {
    process.stdout.write(stats.toString({
        colors: true,
        modules: false,
        children: false,
        chunks: false,
        chunkModules: false
    }))

})
```
请问webpack(config,function(){}) 这个函数的第二个函数里面的内容有什么作用？

Output: 对打包的配置化，如果打包的时候有错误我们就抛出错误，我们可以在webpack()回调里拿到一个stats打包状态，process.stdout.write跟console.log一个意思因为在node环境里console.log也是用process封装的就是向cli里打印输出。但是输出的时候进行了一些格式化。 colors ： 让打包的时候有颜色。 module  : 去掉内置模块信息 children ：去掉子模块 chunks : 增加包信息（设置为 false 能允许较少的冗长输出）chunkModules : 去除包里内置模块的信息


Instruction:
esLint里no-case-declarations的意义在哪
官网的解释：The reason is that the lexical declaration is visible in the entire switch block but it only gets initialized when it is assigned, which will only happen if the case where it is defined is reached.
没怎么看懂

Output:
有中文网站 no-case-declarations
为了保证词法声明语句只在当前 `case` 语句中有效，将你子句包裹在块中。
该规则旨在避免访问未经初始化的词法绑定以及跨 `case` 语句访问被提升的函数。
```
switch (foo) {
    case 1:
        let x = 1;
        break;
    case 2:
        const y = 2;
        break;
    case 3:
        function f() {}
        break;
    default:
        class C {}
}
```
大概是指上面`case 1`里的`x`在`case 2`里也会生效，所以要用`{}`包起来，防止`x`提升到整个`switch`语句。


Instruction:
锤子科技官网banner的动效是如何实现的？
锤子科技官网banner的动效是如何实现的呢？就是图片随鼠标的轨迹移动的动效。以及上方图片文字动效。是CSS3吗？
地址：https://www.smartisan.com/

Output:
```
<style type="text/css">
    .content{
        margin:200px auto;
        width:200px;
        height:200px;
        background: #db473c;
        color:#fff;
    }
    .container {
        transform-style: preserve-3d;
        perspective: 500px;
    }
    </style>
    <div class="container">
    <div class="content"></div>
    </div>
    <script type="text/javascript">
        (function(){
            var content=document.querySelector(".content")
                content.onmousemove=function(e){
                    var evt=e||window.event;
                    var rotateY=-(content.clientWidth/2-evt.offsetX)/10;
                    var rotateX=(content.clientHeight/2-evt.offsetY)/10;
                    content.style.transform=`rotateX(${rotateX}deg) rotateY(${rotateY}deg)`
                }
        }
        )()

    </script>
```


Instruction:
js数组重组
现在有一个数组类似于
var a=[{name:"May",age:12,id:1},{name:"Jone",age:13,id:5},{name:"May",age:15,id:6}];
要把所有name相同的对象重组，大概成为这样的数组
var b = [{
```
name: "May",
list: [{
    name: "May",
    age: 12,
    id: 1
}, {
    name: "May": age: 15,
    id: 6
}]
```
}, {
```
name: "Jone",
list: [{
    name: "Jone",
    age: 13,
    id: 5
}]
```
}]

Output:
```
const a = [{ name: "May", age: 12, id: 1 }, { name: "Jone", age: 13, id: 5 }, { name: "May", age: 15, id: 6 }]

let result = Object.values(a.reduce((m, n) => {
    if (!m[n.name]) {
        m[n.name] = {name: n.name, list: []}
    }
    m[n.name].list.push(n)
    return m
}, {}))

console.log(result)
```