yujianAI/segmentfault_upvote5_clean huggingface dataset:
问题：ES6中如何判断Set和Map等类型
怎么判断这些数据类型?

回答：Chai 有过讨论，这个应该可以满足了
```
function getType(obj) {
     var type = Object.prototype.toString.call(obj).match(/^\[object (.*)\]$/)[1].toLowerCase();
     if(type === 'string' && typeof obj === 'object') return 'object'; // Let "new String('')" return 'object'
     if (obj === null) return 'null'; // PhantomJS has type "DOMWindow" for null
     if (obj === undefined) return 'undefined'; // PhantomJS has type "DOMWindow" for undefined
     return type;
   }
```
```
getType(new Map()) // "map"
```

标签: javascript, ecmascript-6
问题：如何通过onclick添加多个事件？
那天面试官问我一个问题，如何用`onclick`给一个元素添加多个事件。
前提是这个元素已经有一个其它人绑定的事件，在无法修改那个绑定代码的情况下现在你需要再绑定一个，如何做？
```
element.onclick = function(){
  alert(1);
}
```
这个是未知的，只知道已经绑定了一个事件，现在需要添加一个绑定：
```
element.onclick = function(){
  alert(2); 
}
```
请赐教。

回答：面试官估计是想考你给onclick重新包裹一个函数后上下文的切换与参数的传递
```
function addClickEvent(el,fn){
    if(el.onclick){
        var _bak = el.onclick;
        el.onclick = function(e){
            _bak.call(this,e)
            fn.call(this,e)
        }
    }else{
        el.onclick = fn
    }
}
```

标签: javascript, html, 前端, 事件绑定
问题：【mongoose】连接警告：`open()` is deprecated in mongoose >= 4.11.0
mongoose 连接成功，但是发出警告，好像是新版本要修改哪？错误信息如下
```
DeprecationWarning: `open()` is deprecated in mongoose >= 4.11.0，use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`
```
网上找了半天没有结果，求答案，附上连接代码
```
var mongoose = require('mongoose')
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection

db.on('error', console.error.bind(console, '连接错误:'));
db.once('open', function() {
    console.log('连接成功');
})
```

回答：加个{useMongoClient:true}
比如
mongoose.connect('mongodb://localhost/test',{useMongoClient:true})
就可以了，
我是查看：
http://mongoosejs.com/docs/co...
拉下来最后页的The `useMongoClient` Option才知道的

标签: express, mongodb, node.js
问题：es6中export无法向外输出对象变量?
comment.js中定义了一对象
```
const comment = {
  text: 'This is text',
  author: {
    name: 'Sara',
    avatarUrl: 'http://images.ichewbubble.com/01.jpg'
  }
}
```
为什么我用export comment会出错，但是用export default comment就不会出错
还有请问一个js文件中当中只能使用一次export default 吗

回答：需要特别注意的是，export命令规定的是对外的接口，必须与模块内部的变量建立一一对应关系。
```
// 报错 
export 1;

// 报错 
var m = 1; export m;

```
上面两种写法都会报错，因为没有提供对外的接口。第一种写法直接输出1，第二种写法通过变量m，还是直接输出1。1只是一个值，不是接口。正确的写法是下面这样。
```
// 写法一 
export var m = 1;

// 写法二 
var m = 1; export {m};

// 写法三 
var n = 1; export {n as m};

```
上面三种写法都是正确的，规定了对外的接口m。其他脚本可以通过这个接口，取到值1。它们的实质是，在接口名与模块内部变量之间，建立了一一对应的关系。

标签: javascript, ecmascript-6
问题：怎样入门“人工智能-深度学习”领域，包含哪些关键技术？
请已经在此坑中人事给指个方向，例如：该学习什么语言、或框架。整天被“人工智能”这几个字熏陶，感觉在不去了解下就、、、真晚了，求大神指教。

回答：这个问题不是一个糟糕的问题，只是有很多装神弄鬼的大神把人工智能吹到了天上去，就像以前说要想学计算机编程必须要数学好英语好一样，其实不见得。人工智能也是类似，很多人说要想搞人工智能必须会高等代数（甚至装逼到说连高等代数这个名词都不好，必须叫线性代数才牛逼）一样，其实没必要。
实际上，学人工智能分为三个层次：
### 第一层
对于绝大多数人来说，你只要会调用API接口就会人工智能。现在各种开放云全部提供各种人工智能接口，包括百度、阿里等等。需要语音识别吗？调接口就行了；需要图像识别吗？调接口就行了。相信我，你们公司的应用还没有牛逼到必须自己写算法的地步，市面上的各种开放接口所能做到的效果绝对比你自己写的强一百倍。当然，你只到这个层次，没有人会给你百万年薪，如果想要高薪，接着往下看。
### 第二层
对于剩下的人里的绝大多数来说，你还是不需要什么线性代数，如果你想稍微学得深入一些，不想直接使用阿里云的语音识别，而想了解得更深入一些，这时候，你需要学习Python语言或者R语言，对R语言我了解得不多，就以Python为例，这时候有2个框架是你需要知道的：`scikit-learn`, `matplotlib`。光知道了框架也没有用，你得知道你想干什么。就像师傅给你一把斧子和一把锯子，然后呢？接下来，你需要了解一下工具的用法，可以从最简单的泰坦尼克幸存者分类或者鸢尾花分类开始做起。没有什么神秘的，原理很简单：给了你2000个人的姓名、年龄、舱位号，你来预测一下另外1000个人是死还是活？问题够简单吧？这就是“机器学习”！scikit-learn里有几百种不同的算法，你可以一个一个拿来试，直到找到一个预测准确度最高的算法为止。而且scikit-learn已经把所有算法完全包装，甭管多复杂的算法，上来就是三板斧：创建、学习、预测：
```
model = RandomForestClassifier() # 这里你可以随意选择任意算法
model.fit(X_train, y_train)
model.score(X_test, y_test)
```
你觉得这需要多么复杂高深的线性代数吗？你学不会算我输。当然，这时候算法的精度不够高，大概80%多，不到90%的样子，如果你对预测结果的准确率不满意，恭喜你，你又上了一个层次，这时候你可以开始逐渐尝试一些神经网络的库，比如tensorflow的cnn等等，稍微需要一些技巧，不过还是不需要什么线性代数之类的鬼东西，准确度已经可以提升到95%以上了。因为神经网络是分层的，一开始层次不能太多，最多也就是七八层的样子，现在的一些神经网络已经可以提升到100多层，所以就叫深度神经网络，相应的机器学习也就得到了一个牛逼的名字——深度学习。
接下来是你该思考的问题：我能用这些库解决什么实际问题？假设你们公司是开饭馆的，那么能不能预测一下哪个饭点来的客人花钱多？诸如此类的问题，需要你去开动脑筋想一想，然后试着用这些库预测一下，看你的预测准不准。够简单吧？能做这事，大概你到外面能骗到三四十万年薪。
### 第三层
你实在是不爽别人开发的框架（你还是想要获得百万年薪），这时候你可以开发你自己的框架，做出一个比Tensorflow还要牛逼的框架，这个时候你需要用到高等代数了，一般你应该是大学里的一个研究生或者教授，到这个层面，我就帮不上你什么忙了，因为我也还没有修炼到那个程度。不过说真的，你搞这个东西能为公司挣回来百万吗？基本也是不可能的，所以这种算法的虚火要不了多长时间就会灭火，用不着羡慕别人。做这个基本就是觉得好玩去做而已，工程师在任何商业文化里都是被人利用然后唾弃最后资本赚钱的，喜欢就好。
### 附录
最后，英语好的话，可以经常上Kaggle寻摸寻摸，看看别人又在玩什么新花样了，增长眼界的同时也可以练练手。入门教程方面，Cousera上吴恩达教授的机器学习入门还是一门不错的课程，不过需要较好的英语。交朋友方面，可以看看我这篇被众多Java爱好者喷的体无完肤的小文。Python就是牛，在机器学习领域无敌手，哈哈哈！

标签: 人工智能, 机器学习, 深度学习
问题：vue组件注册为什么有时候要在require后面加上default?
手边有两个项目，都是通过vue-cli生成的项目。
其中一个项目可以直接用这样的代码注册组件：
```
Vue.component('HeaderBar',require("./components/common/HeaderBar.vue"));
```
可是另外一个项目却需要这样注册组件：
```
Vue.component('HeaderBar',require("./components/common/HeaderBar.vue").default);
```
否则的话就会报错说：
```
Failed to mount component: template or render function not defined
```
请问这是怎么一回事呢？

回答：webpack 打包时支持 CommonJS、AMD 和 ES6 的模块化系统。

我们通常写 .vue 单文件组件时，在 script 语言块中使用的是 ES6 的语法，使用 export default 进行默认导出。

require 是 CommonJS（和 AMD，想不到吧？）的模块导入方式，不支持模块的默认导出，因此导入的结果其实是一个含 default 属性的对象，因此需要使用 .default 来获取实际的组件选项。或者使用 ES6 的 import 语句，ES6 的模块化导入导出语法参见 http://es6-features.org/#Valu...，import 时需要给定一个变量名，所有 import 语句必须统一放在模块的开头。

如果 .vue 文件中使用的本来就是 CommonJS 或者 AMD 的模块化系统语法，导出的是 module.exports 对象作为组件选项，那么使用 require 导入时就不需要使用 .default 来获取。

以上就是这个问题出现的原因，下面我说说用`webpack`打包`esm`成可直接引入的配置吧。
之前打包`export default`导出的包都会成为
```
{
  default: {
    // 内容
  }
}
```
webpack3多了一个配置
```
libraryExport: 'default'
```
会将`default`中内容打包
```
{
  \\ 内容
}
```

标签: vue.js, webpack, require
问题：Java使用消息队列还是直接使用线程池ExecutorService异步处理？
说说这两种的区别，各自适合什么场景？
用线程池ExecutorService异步处理：我理解`ExecutorService`其实也是内部使用了队列（如`LinkedBlockingQueue`），所以从设计上，其实和使用中间价的消息队列是差不多一致的。只是这里应用服务器既充当生产者又充当消费者，也是消息队列中间价的实现者。这种应该适合非分布式的架构，比如简单的只有一台服务器。
使用消息队列：消息队列（指activeMQ，rabbitMQ，kafaKa，Redis等）因为一般都是中间件，部署在其他机器，需要一定的网络消耗。
本着解耦的目的，使用后者更合理，因为应用服务器一般内存也不会太多，队列长度不易太长。让应用服务器只处理逻辑比较合理。适合分布式架构。
1.使用`JDK`提供的异步框架`ExecutorService`。
```
threadPool.execute(new Runnable() {
    @Override
    public void run() {
        // 这里是异步处理的，比较耗时的逻辑，比如数据库操作
        userService.setDefaultAddressId(user.getUserId(), bookingForm.getAddressId());
    }
});
```
2.将消息发送到消息队列，如使用`redis`的`List`简单实现，然后后台线程消费消息。
```
// 生产消息
redisTemplate.opsForList().leftPush(LOG_MQ_KEY, JsonUtil.beanToJson(httpRequestLog));

// 后台线程异步消费消息
String popValue = redisTemplate.opsForList().rightPopAndLeftPush(LOG_MQ_KEY, TEMP_LOG_MQ_KEY);
```

回答：MQ可以更加有扩展性, 支持的场景更多, 而且支持消息自动的持久化, 建议你看看 RabbitMQ 和 AMQP 协议, JMS 可以学但是没 AMQP 更加通用, redis的MQ还是不要用了, 那只是一个附带的功能, kafka 是大数据领域的不适合做核心业务功能, 只适合数据统计类应用的发送数据, 因为他不确保消息100%不丢失, 如此大的数据量丢一条无所谓的, 不会对统计结果造成影响, 但速度和吞吐量高很多
线程池就不一样了, 目前执行状态你无法知道, msg的消费率是多少都不知道, 消息转发啊, 消息拒绝啊, 都的自己实现, 而且是单机版的, 我目前用他来做一级转发, 就是用他来将 event 异步发送出去, 而不是让他异步做一些很繁重的工作, 举例: 
注册用户service方法, 当事务结束后, 发送 RegisterUserEvent, 这个发送就是用java线程池(如spring的), 然后 RegisterUserListener 监听到了这个 event 就发送 msg 到 Rabbit MQ, 之后对注册用户这个Topic感兴趣的应用都可以订阅, 比如送积分的服务, 送优惠券的服务, 开辟云盘空间的服务等等
java领域有很多这种类比, ehcache 和 redis对比做缓存啊, java并发库 和redis锁对比并发啊等等, 都可以提出你这类型的问题

标签: java, mq, 异步编程
问题：vue中自定义按钮组件为什么要加.native
一直不明白为什么要@click.native = "goback"  我引用过muse-ui里面的自定义组件，很多事件都加了.native 但是我去掉也没关系，只是一直不理解加这个意义是什么。

回答：因为在自定义组件上注册的事件触发的是组件自定义的事件
额 有点绕 举个例子你就明白了
自定义 Button.vue 组件
```
<template>
  <button type="button" @click="clickHandler"><slot /></button>
</template>
```
```
export default {
  name: 'button',
  methods: {
    clickHandler () {
      this.$emit('vclick') // 触发 `vclick` 事件
    }
  }
}
```
引用 Button.vue 组件
```
<vButton @click="clickHandler" @vclick="vClickHandler">按钮</vButton>
```
```
import vButton from '@/components/Button'
export default {
  components: { vButton },
  methods: {
    clickHandler () {
      alert('onclick') // 此处不会执行 因为组件中未定义 `click` 事件
    },
    vClickHandler () {
      alert('onvclick') // 触发 `vclick` 自定义事件
    }
  }
}
```
如果将上面模版改成
```
<vButton @click.native="clickHandler" @vclick="vClickHandler">按钮</vButton>
```
那么两个事件都会执行， `.native` 修饰符就是用来注册元素的原生事件而不是组件自定义事件的
至于你说的 `muse-ui` 中的自定义组件去掉 `.native` 也可以执行 想必是为了方便做了兼容处理
```
<template>
  <!-- 此处自定义事件名也叫 `click` 所以在使用组件时加不加 `.native` 修饰符都可以 -->
  <button type="button" @click="$emit('click')"><slot /></button>
</template>
```

标签: vue.js
问题：求解一道promise笔试题
```
setTimeout(function () {
  console.log(1);
}, 0);

Promise.resolve(function () {
  console.log(2);
})

new Promise(function (resolve) {
  console.log(3);
});

console.log(4);

```
输出：3 4 undefined 1

回答：js中的事件执行主要分为两个任务类型 macro task以及micro task  也就是宏仁务和微任务
宏仁务：script（全局任务），setTimeout ，setInterval ，setImmediate ，I/O ，UI rendering
微任务：process.nextTick，promise,Object.observer,MutationObserver
执行顺序为  script先进入函数调用栈，然后执行遇到任何其他宏仁务，比如遇到了setTimeout，就把setTimeout放进宏仁务队列中，遇到了微任务就放入微任务队列中，等到函数调用栈的所有内容出栈后 然后执行微任务队列，然后再回头执行宏仁务队列再进入函数调用栈再执行微任务队列，知道宏仁务队列执行完毕
在看上面的例子
```
//遇到setTimeout，放入宏仁务队列
setTimeout(function () {
  console.log(1);
}, 0);
//遇到promise，放入微任务队列
Promise.resolve(function () {
  console.log(2);
})
//这里虽然遇到了promise，但是是用new声明的，也就是立即执行，所以会先输出3
new Promise(function (resolve) {
  console.log(3);
});
//第二输出4
console.log(4);

//需要注意的是那个undefined并不是微任务输出的，而是console.log(4)输出的，具体可以控制台测试
----然后执行微任务，这个微任务并没有调用，所以也不会执行，然后执行宏仁务队列中的setTimeout，输出1
```

标签: javascript, node.js
问题：centos7上安装php7，php -v查看php版本，提示命令不存在
在centos7上安装了php7。查看当前运行的进程，有php-fpm。
查找php文件，找到以下这些：
```
[root@demo /]# find . -name php
./var/opt/remi/php71/lib/php
./opt/remi/php71/root/usr/lib64/php
./opt/remi/php71/root/usr/share/php
./opt/remi/php71/root/usr/bin/php
```
运行`which php`,显示没有php：
```
[root@demo /]# which php
/usr/bin/which: no php in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)

```
php -v查看当前php版本，提示命令不存在，要怎么才可以？

回答：1.建立php程序的软连接 sudo ln -s /opt/remi/php71/root/usr/bin/php /usr/bin/php
2.修改rc文件
  1.当前用户的环境变量
```
#如果是使用bash作为shell
vim ~/.bashrc
#增加一行环境变量
export PATH=/opt/remi/php71/root/usr/bin:$PATH
#刷新一下环境变量
source ~/.bashrc
```
2.修改全局环境变量
```
 vim /etc/profile
 export PATH=/opt/remi/php71/root/usr/bin:$PATH
```

标签: php
问题：js对象方法里面为什么不能用箭头函数
先上个代码例子，再说我不理解的地方，求指点，谢谢！
```
var name="window";
var obj={
  name:'netease',
   print1:()=>{
    console.log(this.name);
  
  }
}
obj.print1();//window

```
`es6`中的`this`是定义时绑定，跟运行时无关，我很纳闷就是这个例子中，定义时  `print1`方法里面的`this`不是应该最先查找到的就是`obj`里面的`name`吗，为什么输出是`window`，还是绑定到全局变量上去了?不是明明`print1`里面没有`this`，再查找外围`this`，先找到的应该是`obj`中的`this`吗？

回答：谢邀。
下面这句话引自《深入理解ES6》
箭头函数没有 this/super/arguments/new.target 的绑定，这些值是由外围最近一层非箭头函数决定。
箭头函数的`this`和普通函数的`this`可以看成完全两个概念的东西，不用传统的this去理解。
我对`外围`的理解是，这个外围指的是`()=>{}`整体的外围，比如你的代码中：name属性的外围是什么？print1的外围是什么？。所以 `()=>{console.log(this.name);}`的外围已经出了obj，从而进入window
可以借助我下面的代码来理解：
```
    var name = "window";
    var obj = {
        name: 'netease',
        print1: () => {
            console.log(this.name);
        },
        print3: function () {
            return ()=>{
                console.log(this.name);
            }
        }
    }
    obj.print1();// window
    obj.print3()();// netease 注意是返回闭包函数
```

标签: ecmascript-6, javascript
问题：如何获取vue input的值
```
<template>
  <div class="hello">
    <div class="login">
      <div class="input-wrapper">
        <input  class="input" type="text" placeholder="手机号"  value=""/>
      </div>
      <div class="input-wrapper">
        <input  class="input" type="password" placeholder="密码" value=""/>
      </div>


        <div class="button" @click="login">
          <text class="text">登陆</text>
        </div>

    </div>
   <!-- <toast id="toast"></toast>-->
  </div>
</template>


<script>
  //var modal = weex.requireModule('modal');
  var modal = weex.requireModule('modal');
var stream = weex.requireModule('stream');
  export default {
    methods: {
      login (event) {
        //alert('66');
        stream.fetch({
                    method: 'GET',
                    type: 'json',
                    url: 'http://xxxxxx.com/xxx/xxx?username=ggjz&password=123'
                }, function(ret) {
                    if(!ret.ok){
                        modal.toast({
                            'message': '登陆失败',
                            'duration': 2.0
                        })
                    }else{
                        modal.toast({
                            message: '登陆成功',
                            duration: 2.0
                        })
                    }
                })
      },
    }
  }
</script>

<style scoped>
  .input-wrapper{
    margin-left: auto;
    margin-right: auto;
  }
  .input {
    font-size: 60px;
    height: 80px;
    width: 750px;
  }
  .text{
    color: #666666;
    font-size: 60px;
  }
  .button {
    width: 200px;
    height: 80px;
    text-align: center;
    border-width: 2px;
    border-style: solid;
    border-color: rgb(162, 217, 192);
    background-color: rgba(162, 217, 192, 0.2);
    margin-top: 20px;
    margin-left: auto;
    margin-right: auto;
  }
</style>



```

回答：```
<input v-model="value"/>
```
```
data() {
  return {
    value: ''
  }
}
```
```
this.value //获取
```

标签: node.js, php
问题：php中静态成员方法和静态成员变量是不是不支持多态？
我实现了一个日志工具基类，并派生了两个子类，一个是运维日志类，一个是业务日志类，并在基类中设置了一个静态变量希望能用以区分两个子类，但在调用静态方法时，实际上完全不是想象中的情况，代码如下：
```
// 日志工具基类
class LogTool
{
    protected static $type;
    
    public static function debug($msg) {
        switch (self::$type) {
        case 'biz':
            echo '把日志写入数据库表1';
            break;
        case 'opt':
            echo '把日志写入数据库表2';
            break;
        default:
            echo 'error';
        }
    }
    
    // 其他代码省略
}

// 运维日志类
class OptTool extends LogTool
{
    protected static $type = 'opt';
}

// 业务日志类
class BizTool extends LogTool
{
    protected static $type = 'biz';
}

// 调用代码
BizTool::debug('王小虎已登录');

```
代码如上，实际上函数 dosomething 的运行情况是每次都输出 'error'，因为在执行静态方法debug时，静态成员 $type 是空值；
但是如果我把 debug 函数在子类中再实现一次，则运行时 $type 变量就是有值的。
可是这样做就完全没意义了，抽象父类出来就是为了减少重复代码的，现在两个子类除了写入日志的表不同，其他完全相同，结果这样的结果弄得我欲哭无泪。
非常简要地回答就行

回答：基类中采用static::的方式，可以覆盖当前基类中定义的静态变量/方法，而去使用子类中定义的静态变量/方法。

标签: php
问题：redis 失效的key造成的问题
是这样得
```
//这里面执行判断是否存在缓存
$res = redis -> get("xxx");
if($res != null){
  //返回缓存结果
  return $res;//缓存返回
}

$res = db -> query("select * ...")//假设这句要3秒

redis -> setex("xxx",3600,$res)//保存到缓存，3600时间
//返回查询结果
return $res;

```
大概意思是这样的,就是我先从缓存取，没有就从数据库取，且存到缓存中，方便下次再去取。
但是问题就来了，假设我有千万并发，xxx 这个key存在3600,3600时间后自动销毁，必须得重新从数据库获取，而这句sql要3秒，3秒钟并发了几千万，就是查了几千万次数据库，必须得第一条成功缓存下来,后续的才不会跳过缓存返回那句，但这期间3秒却足以使服务器垮了，我想问的是怎样才能只访问一次数据库，其他那几千万访问都是从缓存取。

回答：可以看看这篇博文：缓存更新的套路
补充：
缓存被“击穿”问题（以前看过一篇文章的做法，你可以借鉴一下）：
业界比较常用的做法，是使用mutex。简单地来说，就是在缓存失效的时候（判断拿出来的值为空），不是立即去load db，而是先使用缓存工具的某些带成功操作返回值的操作（比如Redis的SETNX或者Memcache的ADD）去set一个mutex key，当操作返回成功时，再进行load db的操作并回设缓存；否则，就重试整个get缓存的方法。类似下面的代码：
```
 public String get(key) {
      String value = redis.get(key);
      if (value == null) { //代表缓存值过期
          //设置3min的超时，防止del操作失败的时候，下次缓存过期一直不能load db
          if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //代表设置成功
               value = db.get(key);
                      redis.set(key, value, expire_secs);
                      redis.del(key_mutex);
              } else {  //这个时候代表同时候的其他线程已经load db并回设到缓存了，这时候重试获取缓存值即可
                      sleep(50);
                      get(key);  //重试
              }
          } else {
              return value;      
          }
  }
```

标签: php, redis, 缓存
问题：求解一道关于js的百度笔试题
```
var name = "World";
(function () {
  if (typeof name === 'undefined') {
    var name = 'Jack';
    console.log('Goodbye' + name);
  } else {
    console.log('hello ' + name);
  }
})()

```
输出：GoodbyeJack

回答：变量声明提升: 变量的声明会提升到当前作用域的顶部
你的代码等于
```
var name = "World";
(function () {
  var name //声明提升
  if (typeof name === 'undefined') {
    name = 'Jack';
    console.log('Goodbye' + name);
  } else {
    console.log('hello ' + name);
  }
})()

```

标签: javascript
问题：react不能给组件绑定点击事件吗？
这是我的点击事件：
```
useCoupon=()=>{
    console.log(444444)
};

```
这是我的DOM结构：
```
<div className="select-wrapper-inner">
  {
    this.state.availableCouponList.map((item,index)=>{
      return (
                 <SingleCoupon key={index} onClick={this.useCoupon} price={item.price} condition={item.condition} deadline={item.deadline}/>
             )
    })
   }
</div>

```
我现在绑定的这个点击事件不会被触发，什么意思？SingleCoupon是我自定义的一个组件

回答：SingleCoupon是你定义的组件，并不是一个真实的DOM元素，它不存在点击事件，因为它不是最终渲染的页面的元素。
你应该这样用
```
class SingleCoupon extends Component {
    render() {
        return (
            <div onClick={this.props.onClick}/>
        )
    }
}

```
所有的事件处理函数都必须要绑定到真实的DOM上。传给组件，组件只会认为它是个prop

标签: react.js
问题：js对象为什么不能直接操作？
发现一个小问题，在控制台输入{a:1}.toString()会报错，必须要先把{a:1}赋值给一个变量然后在进行操作才行，这是什么情况

回答：因为语法规定。
因为语法规定导致 js 解释器没有正确理解你的意图。解决办法, 加括号消歧义。
```
({a:1}).toString() // or
({a:1}.toString())
```
## 引申
开始以为是 console 的锅，后来发现 node CLI 里一样存在这个问题，于是发现里蹊跷：
花括号 `{}` 除了可以用来定义对象字面量，还可以用来定义代码块。
冒号`:` 除了可以用来定义对象字面量中的 key-value 对外，还可以用来定义 `label`
label的概念
如果你听说过 C 语言（js就是C系的语法），你听说过有个语句叫 `goto`，那你应该对 `label` 有印象。js 里没有 `goto`，但是有 `break` 和 `continue`, 这俩货可以和 `label` 连用。
`{a:1}.toString()` 之所以报错 `unexpected token .` ，是因为它被解析成了：
```
{
// code block
a: // 定义一个label，名字叫a

1 // 这是一条语句，就一个数值 1
 
}
// block 结束了
.toString() // 报错，非法字符`.`
```
所以你可以这样玩：
```
{
  a:console.log(1);console.log(2);
}
```
这代码语法正确，能执行！

标签: javascript
问题：从mysql查出200万数据有什么好的办法
查询的时候老是崩溃

回答：不要用分页，查到后面越查越慢。
因为
```
limit 10000,100
```
这种那个10000是会查询然后丢弃的。
正确的做法是用游标。
假设你的游标字段为`id`
```
$cursor = 0;
$size = 1000;
do {
$sql = 'SELECT * FROM user WHERE id > :id ORDER BY id DESC limit :size';
$data = 执行查询得到的数组。
$count = count($data);
foreach($data as $row){
    $id = $row['id'];
//处理数据
}
// 当前条数不大于size，证明下面没数据了。
if($count<$size){
    break;
}
}while(true);
```
这种是利用mysql查询筛选【一部分你要的数据，不存在数据丢弃】。所以速度一直都很快

标签: php, mysql
问题：请问大家某些大牛常说不要做“api程序员”，这里的api一般是哪些api呢？ 像 环信 融云 这样的算api吗 ？
请问大家某些大牛常说不要做“api程序员”，这里的api一般是哪些api呢？ 像 环信 融云 这样的算api吗 ？本人是做php开发的

回答：API（Application Programming Interface,应用程序编程接口）是一些预先定义的函数，目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力。我们在写程序时，无疑会调用各种第三方库的API来实现功能。
从描述看，问题中的API指的是Web API，这里的API并不是特指某个服务的API。
对于Web API而言，仅仅调用别人的API来实现业务功能，或者说，自己仅仅是从数据库中取数据，写简单的增删查改的API，这类工作的技术含量是很低的，所以不要做“API程序员”
一个好的Web开发者，应当是需要具备比较深厚的编程功底的。比如数据结构、算法等，做web开发，需要知道restful规范，HTTP协议，负载均衡，分布存储等知识。这些要求就会高得多了。
简而言之，你需要去做一些技术含量高的东西，简单的API调用很基本，刚学了几天web开发的程序员就会调用，这不能构成任何的竞争力。大量轮子已经造好，完全从零开始不实际的，需要关注的是，你的代码中算法和模型这些核心占比多少，纯粹的API调用占比多少，调用的API内部实现的机制了解多少，不要只是简单调用。

标签: api, php, 编程风格
问题：golang time.Now() 格式化的问题。
golang中使用time.Now().Format("2006/1/2 15:04:05") 格式化时间输出时，Format的参数必须是"2006/1/2 15:04:05",这个时间为例的时间格式吗？
```
func main() {
    now := time.Now()

    fmt.Println(now)
    
    // 必须使用这个时间才能返回正确的格式化后的时间，其他的都不行
    fmt.Println(now.Format("2006/1/2 15:04:05"))
    fmt.Println(now.Format("2006/01/02 15:04:05"))
    fmt.Println(now.Format("15:04:05 2006/1/2"))
    fmt.Println(now.Format("2006/1/2"))
}

```
请问"2006/1/2 15:04:05"这个时间有什么历史典故吗？

回答：这个是我以前收藏的笔记
go 的time package 提供了time.Format函数，用来对时间进行格式化输出。
类似的还有time.Parse用来解析字符串类型的时间到time.Time。这是两个互逆的函数。
问题是，go 采用的格式化 layout 和我们以往所用的任何经验都不同。以至于初次接触总是一头雾 水。
其实 go 提供的这个 layout 对算法的实现非常科学高效，而且很规律。下面我们详细分解下。 直接上个对应表
前面是含义，后面是 go 的表示值,多种表示,逗号","分割
```
月份 1,01,Jan,January
日　 2,02,_2
时　 3,03,15,PM,pm,AM,am
分　 4,04
秒　 5,05
年　 06,2006
时区 -07,-0700,Z0700,Z07:00,-07:00,MST
周几 Mon,Monday

```
您看出规律了么！哦是的，你发现了，这里面没有一个是重复的，所有的值表示都唯一对应一个时间部分。并且涵盖了很多格式组合。
比如小时的表示(原定义是下午3时，也就是15时)
```
3 用12小时制表示，去掉前导0
03 用12小时制表示，保留前导0
15 用24小时制表示，保留前导0
03pm 用24小时制am/pm表示上下午表示，保留前导0
3pm 用24小时制am/pm表示上下午表示，去掉前导0

```
又比如月份
```
1 数字表示月份，去掉前导0
01 数字表示月份，保留前导0
Jan 缩写单词表示月份
January 全单词表示月份

```
实例对应
真实时间：我的UTC时间是 2013年12月5日，我的本地时区是Asia
字符表示：　　2013 12 5 Asia
Go Layout：　2006 01 2 MST
真实时间：我的UTC时间是 2013年12月22点，我的本地时区是Asia
字符表示：　　2013 12 22 Asia
Go Layout：　2006 01 15 MST
是滴，上面这个时间是合法的，虽然没有说是那一天，但是说了小时
而所有这些数字的顺序正好是1,2,4,5,6,7和一个时区MST
其实还有一个秒的 repeated digits for fractional seconds 表示法
用的是 0和9 ,很少用，源代码里面是这样写的
stdFracSecond0                          // ".0", ".00", ... , trailing
zeros included stdFracSecond9                          // ".9", ".99",
..., trailing zeros omitted
那些分界符
除了那些值之外的都是分界符号，自然匹配了，直接举例子吧
字符表示：　　2013-12 21 Asia
Go Layout：　2006-01 15 MST
字符表示：　　2013年12月21时 时区Asia
Go Layout：　2006年01月15时 时区MST
好了，您是否感觉这个表示方法兼容度更好，适应性更强呢，更容易记忆呢。

标签: go, time, 格式化
问题：javascript把json对象转为数组
转换前是这样的：
```

var articles = [{
    title: 'hello',
    content: 'hello world',
    created_at:'2017-08-30 13:45:15'
},{
    title: 'foo',
    content: 'foo bar',
    created_at:'2017-08-30 13:45:15'
}];
```
我想把它转成这样：
```
var articles2 = [
    [ 'hello', 'hello world', '2017-08-30 13:45:15' ],
    [ 'foo', 'foo bar','2017-08-30 13:46:06' ]
];
```
用js应该怎么做呢？

回答：```
var articles = [{
    title: 'hello',
    content: 'hello world',
    created_at:'2017-08-30 13:45:15'
},{
    title: 'foo',
    content: 'foo bar',
    created_at:'2017-08-30 13:45:15'
}]
var result = articles.map(item => {
  return Object.values(item)
})
```

标签: javascript
问题：如何用Laravel 做Api接口
我想用laravel做个api接口，但是作为接口，应该对请求做校验，我能想到将校验的数据放到header中，在laravel的中间件对header做校验，但是我现在不知道拿到header怎么去用。
还有就是做api对请求校验的作用，重要性

回答：API接口的校验有很多种，看你的API是用在哪方面，APP还是web。
也不一定非要放在header中，使用基础的signature方案也能完成对接口的校验。
signature方案：客户端和API使用同一套加密规则，提供一个APPkey和secret，然后经过secret加密（或者其他处理过程）生成signature，传输的时候将signature和appkey作为参数传递。这是目前用的比较多的一种API接口调用权限校验，只是用来校验客户端是否有权限调用API。
JWT: JSON WEB TOKEN 也是一种可选的，只不过他更复杂， 更多的是用来校验用户的登录状态和权限，（用在APP、无状态的web系统），关于JWT有相对应的 composer 包可选择。核心思想就是，API加密一个uid或者其他标识，生成一个token，这个token是有时限的，比如两个小时，放在header的Authorization中，通过获取进行校验，（涉及用户的操作，一般会传递uid或者其他类似标识字段），通过JWT进行权限校验即可。
至于拿到 header 怎么用，如果是JWT 取出 Authorization字段，以及标识字段（如UID）然后进行JWT校验即可，加密和校验可以自己实现，不过建议使用成熟的composer包吧，比如我用过的：https://github.com/lcobucci/jwt。
看你到底需求什么校验 是 `用户鉴权` 还是 `API接口调用权限校验`，个人认为这两者是不同的。
另外API请求校验的作用很明显，别人即使知道你的API，也无法调用。（这个无法调用是相对的，如果你的signature校验写的很死，尤其是可以多次应用的signature，就存在重放攻击）。
用户鉴权这个就更不用说了，不同的用户只能操作自己权限的东西，不鉴权的API，是存在各种问题的。

标签: php, laravel
问题：angular 对象？.语法的具体含义
在angular项目的html中，比如a是个对象，a？.b这句语法是什么意思，是angular中特有的吗？还是问号运算符本身就有的功能，如
```
<div>
    {{ foo?.bar }}
</div>
```

回答：`?.`是angular模板中的安全属性操作符语法，属于angular模板特有语法
`a?.b`表示当a存在时(不为null或undefined)，取`a.b`的值，否则置空；以避免出现a未赋值时直接报错
详见官方文档The safe navigation operator ( ?. ) and null property paths

标签: typescript, javascript
问题：vue-router的beforeEach导航钩子，next('/')出现死循环问题
为什么next()指定路径会出现死循环
```
router.beforeEach((to, from, next) => {
  console.log('beforeEach');
  if(true){
    next('/');
  }else{
    next();
 }
});
```

回答：next()直接跳转到to.path路径，没有再执行一遍beforeEach导航钩子，next('/')或者next('/login')自己指定路径的，路由跳转的时候还执行一遍beforeEach导航钩子，所以上面出现死循环；
栗子：如我们登录页（'/login'）面进入首页('/')，可以这么写：
```
router.beforeEach((to, from, next) => {
  var userInfo= JSON.parse(sessionStorage.getItem('userInfoStorage'));//获取浏览器缓存的用户信息
  if(userInfo){//如果有就直接到首页咯
    next();
  }else{
    if(to.path=='/login'){//如果是登录页面路径，就直接next()
      next();
    }else{//不然就跳转到登录；
      next('/login');
    }

  }
});
```

标签: vue.js, vue-router
问题：短信验证码是前端做还是后端？
1.短信验证码接口是前端做的吗？  我们后台是php
2.前端需要做什么工作啊？
我以前没有做过这种事，求大神指导

回答：初步实现步骤：
```
1、 用户：填写手机号码
2、 用户：点击发送短信
3、 js  ：调用后端接口，提交手机号码-告知后端发送短信
4、 后端：生成随机码，作为验证码
5、 后端：保存随机码-
6、 后端：调用短信接口-将随机码发送给用户
7、 用户：接收到短信，填写验证码
8、 用户：点击提交按钮
9、 js  ：调用后端接口，提交手机号码、验证码
10、后端：根据手机号码获取保存的验证码，与接收到的验证码对比，是不是一样的
11、js  ：判断后端返回的结果Y/N
12、js  ：反馈用户

```
可以另外再做些优化
```
a、限制用户多次提交
b、后端保存的随机码加个时间限制，
。。。
```

标签: javascript, php
问题：什么是跳板机？
什么是跳板机？

回答：跳板机，就是可以给你远程连接的机器，然后通过这个机器再去访问别的机器，这个跳板机可以是`windows`下也可以是`Linux`下，跟操作系统无关，下面是其中比较常见的一种场景：
很多客户方的服务器外网是连接不了的，一般只能通过`VPN`然后才能连接，然而一些客户方觉得做`VPN`的代价太大，但是开发方不方便经常去现场或者其他原因需要访问客户方的服务器并且服务器外网不能连接时，没有`VPN`时，只能通过远程连接，比如`teamview`,`QQ`远程，还有`windows`自带的远程连接工具，连接到远端的一台电脑上，这台电脑就是跳板机，作为一个桥梁，然后再通过这个机器在内网中访问其服务器

标签: linux
问题：相对于前端来说，SDK指的是什么？
请问 相对于前端开发来说 SDK指的是什么？
- 是API接口？
- 是一段注入JS？
求大大给解惑解惑！

回答：假设我开发了一个博客后台管理系统，开放了一系列功能操作的HTTP或其他协议的接口，用于创建博客、发布文章、文章列表、发布评论、对文章以及评论点赞等操作，那么这个叫API，用于其他程序方便通过接口实现博客功能。
一般情况下有可能到这一步，我的博客系统就打完收工了。
但是某一天有一个合作伙伴说，你们这一堆API，我熟悉起来要半天，能不能更加方便我来接入，那我问他你用什么语言，他说我就会javascript，那么我就用js写了一堆类和方法，把我的API接口封装起来，用户不需要关心接口地址等，只需要引入我封装的js的url，就可以通过类和方法就可以发布文章、创建博客、文章列表等，这个就叫SDK，当然这个SDK很简单，可能就是一个或几个js文件以及简陋的不能再简陋的文档。
复杂的SDK其实是一整套完整的解决方案，比如IOS APP开发，苹果提供的SDK其实包含了开发工具Xcode、ios各种版本的sdk、帮助文档、命令行工具等等一些列东西

标签: 前端
问题：laravel 路由冲突
跟着网上视频学习laravel5.4，写了下面两行代码。
Route::get('/posts/{post}','AppHttpControllersPostController@show');
Route::get('/posts/create','AppHttpControllersPostController@create');
然后视频中访问localhost/laravel/public/posts/create 结果是成功的，而我访问却跳转到了show中，求解？？

回答：加一个正则表达式限制就好了，默认情况下，`laravel` 的路由匹是从上往下的，匹配到符合的第一条后，就不会往下匹配了：
```

//假设post为int
Route::get('/posts/{post}','AppHttpControllersPostController@show')->where('post', '[0-9]+');
Route::get('/posts/create','AppHttpControllersPostController@create');

```

标签: php
问题：php 的yield叫协程，go的goroutine也叫协程，它这两种完全不一样吧？
php那个我是没搞懂，而且是会暂停的。
go那个呢，并不需要暂停，我就是类似另开一个线程，做完了事，返回数据，就闪人，这个还更好理解。PHP那个有点搞不懂。

回答：在`php`等语言里的`yield`，不是`协程`语法，而是`迭代器`语法。  
而包括`php`在内的大多数语言实现`迭代器`的方式，是通过一个可中断的函数完成的。  
而`协程`的一个特点就是执行中断，切换上下文。  
所以就有了通过`迭代器`函数去`实现`协程的方案。这种方案充分利用了`迭代器`可中断的特点来模拟`协程`中断，而利用闭包函数的上下文独立性，实现`协程`的上下文切换。  
总结起来，什么是协程，协程是通过切换运行方法和上下文，来在同一个空间中完成不同的处理任务（注意，不是另外开线程）。  
那么协程怎么实现，`goroutine`就是协程的一种实现方式。  
而通过`迭代器`实现协程，就又是另外一种方式。  
两者的区别在于，`goroutine`是已经存在的实现。相当于已经成品的车，你理解起来会相当容易。  
而`迭代器`只是提供者实现`协程`的方法，具体要实现协程，还需要自己去写代码完成。这就好像是汽车的零件，你需要自己组装，所以还需要深入学习你才能理解它的原理

标签: php, go
问题：php如何打包下载远程图片
现在页面上有多张图片（来自 OSS）,如何根据这些图片的 url 来一次性将图片全部下载到本地？

回答：如果你想在 浏览器端做这个功能就需要借助 js 实现
如果你想在 服务端实现这个功能，可以一张一张获取，然后打包。
From : https://stackoverflow.com/que...
```
$image1 = "http://cdn.screenrant.com/wp-content/uploads/Darth-Vader-voiced-by-Arnold-Schwarzenegger.jpg";
$image2 = "http://cdn.screenrant.com/wp-content/uploads/Star-Wars-Logo-Art.jpg";

$files = array($image1, $image2);

$tmpFile = tempnam('/tmp', '');

$zip = new ZipArchive;
$zip->open($tmpFile, ZipArchive::CREATE);
foreach ($files as $file) {
    // download file
    $fileContent = file_get_contents($file);

    $zip->addFromString(basename($file), $fileContent);
}
$zip->close();

header('Content-Type: application/zip');
header('Content-disposition: attachment; filename=file.zip');
header('Content-Length: ' . filesize($tmpFile));
readfile($tmpFile);

unlink($tmpFile);
```

标签: php
问题：为什么.vue文件需要使用export default
```
因为项目要使用vue开发。学习了一段时间之后有几个问题一直困惑着我：
（1）首先就是.vue结尾的文件为何需要export default，就像下面的代码一样？
（2）为什么data需要return，我不用return，直接 data(){
    menu:MENU.data,
    poi:POILIST.data
}不行吗？
这两个问题问了几个人都不能给我合理的解释，求懂的兄弟们给个帮助，谢谢了。

```
```
<script>
    import { POILIST, MENU } from '../config/vuex.js';
    export default {
        data() {
            return {
                menu: MENU.data,
                poi: POILIST.data
            }
        },
        methods: {
            set() {
                MENU.list.push('首页');
                POILIST.list.push({
                    lng: 124.1,
                    lat: 42.3
                });
            }
        }
    }
</script>
```

回答：export default是ES6的语法，意思是将这个东西导出，你要import 引入东西，导出了才能引用，data是一个函数是因为data是被很多组件共享的，如果 data 是一个的对象的话，每次实例化会造成所有的实例共享引用同一个数据对象，如下
```
var fnc= function() {}
fnc.prototype.data = {
  a: 1,
  b: 2,
}

var fnc1 = new fnc()
var fnc2 = new fnc()

fnc1.data.a === fnc2.data.a // true
fnc2.data.b = 1;
fnc2.data.b // ==1
```
data 是函数的话，每次创建一个新实例后，调用 data 函数，用return返回初始数据的一个全新副本数据对象，就避免了所有实例共享引用同一个数据对象。

标签: javascript
问题：npm install -g 和npm install --save-dev的关系
npm install --save-dev xxx是自动把模块和版本号添加到devdependencies部分
npm install -g xxx是将模块安装在全局
但是执行了npm install --save-dev，package.json中devDependencies会加入安装的模块，但是在命令行中执行命令时还是出现command not found，还是必须要npm install -g安装在全局才行。
npm install --save-dev的作用仅仅是自动把模块和版本号添加到devdependencies部分么，我们还是需要先安装么？还是说我们没配对环境变量？ 为什么很多教程在Installation这流程都是npm install --save-dev xxx就OK了呢

回答：1.`npm install`本地安装
（1）将安装包放在 ./node_modules 下（运行 npm 命令时所在的目录），如果没有 node_modules 目录，会在当前执行 npm 命令的目录下生成 node_modules 目录。
（2）可以通过 require() 来引入本地安装的包。
2.`npm install` -g全局安装
(1) 将安装包放在 /usr/local 下或者你 node 的安装目录。
(2)可以直接在命令行里使用。
3.`npm install --save`
(1)会把msbuild包安装到node_modules目录中
(2)会在package.json的dependencies属性下添加msbuild
(3)之后运行npm install命令时，会自动安装msbuild到node_modules目录中
(4)之后运行npm install --production或者注明NODE_ENV变量值为production时，会自动安装msbuild到node_modules目录中
4.`npm install --save-dev`
(1)会把msbuild包安装到node_modules目录中
(2)会在package.json的devDependencies属性下添加msbuild
(3)之后运行npm install命令时，会自动安装msbuild到node_modules目录中
(4)之后运行npm install --production或者注明NODE_ENV变量值为production时，不会自动安装msbuild到node_modules目录中

标签: javascript, node.js, npm
问题：React-Router V4+ 打包后刷新网页404错误
开发使用的构建工具是 create-react-app
我在使用 React-Router V4+ 版本的时候，
```
npm run build
```
编译成功后放在我本地的 Tomcat9 上，运行后可以正常访问首页，跳转其它页面 URL 都正常显示， 但是再刷新当前页面404错误。
按照官方提示：
There is also a similar approach for Apache servers. Create an .htaccess file in your folder's root:
```
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
```
问题1 ：
创建了 .htaccess 文件后，该文件是放在我编译好的包的根目录（index.html所在目录）下，还是在 其它位置。如果需要修改其它东西如 Apache 配置文件，要怎么修改。
问题2 ：
在网上看到这种情况都是将 URl 重定向到 index.html，请问还有其它不修改服务器配置文件的解决办法没有。
跪求解答，谢谢

回答：我没看过文档，建议你要理解内部的机制。
之所以你在浏览器内可以由首页跳转到其他路由地址，是因为这是由前端自行渲染的，你在React Router定义了对应的路由，脚本并没有刷新网页访问后台，是JS动态更改了location。
当你刷新时，你首先是访问的后台地址，然后返回的页面内加载了React代码，最后在浏览器内执行；也就是说如果这个时候报404，是因为你后台并没有针对这个路由给出返回HTML内容，也谈不上执行React Router了。
解决办法就一条：如果你期望所有的路由都由React Router来定义，只有你的后台，无论任何路径，都返回index.html就好了。剩下的事情交给React Router。那么你要做的就是修改后台服务器，可以放在apache，也可以放在你的java路由内做一个通配路径处理。

标签: javascript, react.js
问题：如何用 javascript 实现多字段模糊查询
数组如下
```
var arr = [
    {id: "1", en: "Afghanistan", cn: "阿富汗", code: "93"},
    {id: "2", en: "Iraq", cn: "伊拉克", code: "964"},        
    {id: "3", en: "Qatar", cn: "卡塔尔", code: "974"}
    ]
```
en,cn,code都能查询
比如输入`aq`，查询返回第二条
比如输入`卡`，查询返回第三条
比如输入`97`，查询返回第三条

回答：```
function query(arr, q) {
  return arr.filter(v => Object.values(v).some(v => new RegExp(q + '').test(v))
  )
}
```

标签: javascript
问题：在命名规范的情况 你还会写注释么？
比如一些方法
```
// 封装链路信息数据
formatLinksInfo() {}

// 获取节点坐标数据
getNodesPosition() {}

// ip转数字
ipToNum() {}

// 判断元素是否全部选中
isAllElemsActive() {}

// 右键菜单选项
itemContextMenu() {}

if(target.classed('topo')){} // 拓扑图情况
if(target.classed('node')){} // 节点
if(target.classed('link')){} // 链路
```
比如像这种命名 不写注释感觉也能通过方法名或者类名 也能看懂，
但自己还是都写了 现在code review看来觉得很冗余
问一下你们关于代码注释编写原则是啥呢，能通过命名读懂的都不写么？

回答：- 你不应该在每次调用方法的时候写注释，而是应该在声明函数的地方写注释
- 
建议每个函数都写相应的注释

你自己写代码存在主观性，你觉得规范，其实不一定规范，或许可以说不一定全面;
每个人理解方法是不一样的，你觉得命名规范了，那也许是真的很规范，但是并不是所有人都能一下子看懂，如果要整个遍历一下方法实现过程这是非常浪费时间的，别人看到一个函数应该立刻能从注释和方法名知道这个函数是干什么的;
函数名写的再好，我也只能大概猜到这个函数是干什么的，但是我对函数的参数和返回值类型等信息一无所知
总而言之，空间换时间，一次时间换以后的`N`次时间是非常值得的


- 建议写英文注释，这样`review`起来更加简洁，不显得那么格格不入，不要觉得什么自己或者其他人英文底子不好，网上各种英汉词典，多写英文注释遇到不知道的还能多学几个英文单词

建议每个函数都写相应的注释
- 你自己写代码存在主观性，你觉得规范，其实不一定规范，或许可以说不一定全面;
- 每个人理解方法是不一样的，你觉得命名规范了，那也许是真的很规范，但是并不是所有人都能一下子看懂，如果要整个遍历一下方法实现过程这是非常浪费时间的，别人看到一个函数应该立刻能从注释和方法名知道这个函数是干什么的;
- 函数名写的再好，我也只能大概猜到这个函数是干什么的，但是我对函数的参数和返回值类型等信息一无所知
- 总而言之，空间换时间，一次时间换以后的`N`次时间是非常值得的

标签: 前端, 代码规范, javascript, php
问题：Vue路由的$router.back(-1)回退时如何判断有没有上一个路由
现在每个页面的左上角有一个返回按钮<
点击时的代码是this.$router.back(-1)，返回上一个路由
但是我们现在有这样一个需求，把其中某一页分享出去，用户打开时并没有上一条路由的历史记录，所以点击<按钮时没有反应。
所以应该怎么判断有没有上一条路由的历史记录。
代码：
routerback: function () {
  this.$router.back(-1)
},

回答：在页面一开始加上一个全局的函数：
```
activated: function () {
  this.$setgoindex()
}
```
这个函数是这样的，判断当前页面的历史记录是不是小于等于1，如果小于等于1，说明这个页面没有可以返回的上一页，如果没有可以返回的上一页，就给地址栏加上一个goindex=true的参数，这样你从这个页面在往下一个页面跳转在返回，这个参数就一直加上的
```
Vue.prototype.$setgoindex = function () {
  if (window.history.length <= 1) {
    if (location.href.indexOf('?') === -1) {
      window.location.href = location.href + '?goindex=true'
    } else if (location.href.indexOf('?') !== -1 && location.href.indexOf('goindex') === -1) {
      window.location.href = location.href + '&goindex=true'
    }
  }
}
```
然后在左上角返回按钮加上这个逻辑：
```
if (this.$route.query.goindex === 'true') {
  this.$router.push('/')
} else {
  this.$router.back(-1)
}
```
这样就可以了

标签: vue.js, vue-router, vuex, vue-loader
问题：axios 可以挂在Vue原型上 为啥还有个vue-axios?
如题，这个vue-axios有什么其他用途还是多余的？
因为
```
Vue.prototype.$http = axios
和
import Vueaxios from ‘vue-axios’
Vue.use(VueAxios,axios)

```
这二者效果都是一致，这样我就感觉vue-axios显得多余。希望知道多一点的朋友，能告诉我vue-axios存在的必要，非常感谢！

回答：何不看看vue-axios的源码，就一个文件：
index.js
```
(function () {

/**
 * Install plugin
 * @param Vue
 * @param axios
 */

function plugin(Vue, axios) {

  if (plugin.installed) {
    return
  }
  plugin.installed = true

  if (!axios) {
    console.error('You have to install axios')
    return
  }

  Vue.axios = axios

  Object.defineProperties(Vue.prototype, {

    axios: {
      get() {
        return axios
      }
    },

    $http: {
      get() {
        return axios
      }
    }

  })
}

if (typeof exports == "object") {
  module.exports = plugin
} else if (typeof define == "function" && define.amd) {
  define([], function(){ return plugin })
} else if (window.Vue && window.axios) {
  Vue.use(plugin, window.axios)
}

})();
```
首先是按照`Vue`的插件文档来写的，直接绑在原型链上不是不可以，如果像您这样注册一个$http，和项目其他成员协作的时候就必须注明你注册的变量名称，而使用vue-axios大家就没有歧义了。
说白了，使用vue-axios更多是为了符合规范，并且方便协作吧。

标签: vue.js, axios, vue-resource
问题：react native使用 react-navigation登录后如何清空 react-navigetion 内的返回记录？
如题所说，使用navigation 导航，登录后清空记录，navigation有相应的方法吗???????

回答：跳转并清空路由记录
```
 import { NavigationActions } from 'react-navigation'
 resetAction = NavigationActions.reset({
                index: 0,
                actions: [
                    NavigationActions.navigate({routeName:'xxx'})//要跳转到的页面名字
                ]
            });
this.props.navigation.dispatch(resetAction);
```

标签: react.js, react-native
问题：移动端页面使用background-attachment:fixed;固定背景图片
在某些机型中微信中打开不起作用，大家遇到过没？怎么解决的呢

回答：移动端对`background-attachment: fixed`支持的不好，但可以hack一下。
```
cssbody:before {
  content: ' ';
  position: fixed;
  z-index: -1;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: url(path/to/image) center 0 no-repeat;
  background-size: cover;
}

```

标签: html
问题：怎么用js通过文件的url下载文件到本地
目前拿到的是文件的url，不是下载地址，只是文件的存放地址。前端怎样用js通过这个url实现文件的下载呢？

回答：```
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
</head>
<body>
    <a href="/download/papers/abc.doc">点击链接下载</a>
    <button onclick="download1()">点击按钮下载</button>
      <button onclick="download2">点击按钮下载</button>

    <script>
        // 会打开一个空白页下载，然后空白页消失，用户体验不好
        function download1() {
            window.open('/download/papers/1');
        }
      
        // 直接下载，用户体验好
        function download2() {
            var $form = $('<form method="GET"></form>');
            $form.attr('action', '/download/papers/1');
            $form.appendTo($('body'));
            $form.submit();
        }
    </script>
</body>
</html>
```

标签: javascript, jquery, 前端
问题：请问 React 中的 registerServiceWorker是干什么的？
create-react-app生成的项目中，多了一个registerServiceWorker.js，并且在 index.js 中引用，请问这个registerServiceWorker是什么东西，融合进 react 的目的是什么？

回答：看下注释你就知道了，主要是用于在生产环境中为用户在本地创建一个`service worker` 来缓存资源到本地，提升应用的访问速度，具体看下面这段注释。
```
// In production, we register a service worker to serve assets from local cache.

// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on the "N+1" visit to a page, since previously
// cached resources are updated in the background.

// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
// This link also includes instructions on opting out of this behavior.
```

标签: react.js
问题：jQuery修改input的val能否触发v-model的更新
现在有需求，希望能通过jQuery修改input的值，并且能触发相关数据的更新，能不能办到。比如
```
$("input").val(2333);
```
我的需求比较奇葩啊，页面上有循环出来的大量input框，而这些input框需要通过一个自定义的键盘来输入。用jQuery的话只要在需要修改的input上打标记，然后再改它的值就行。只用vue的话目前没想到有啥简单的方法来实现。
现在的想法是，实在不行就在每个input上打上数组的维度标记，然后用jQuery根据维度去data中修改对应的值。这么一来就有点麻烦了

回答：可以的，需要在设置完之后触发一下事件:
```
$("input").val(2333)
//触发一下该input的input事件
$("input")[0].dispatchEvent(new Event('input'))
```
`v-model` 只不过是个语法糖，底层还是监听的input事件

标签: vue.js, javascript
问题：css 当a的父节点是p 的话,该怎么表达呢?
```
<p><a></a><p>
```
这种该怎么表达呢?主要是给p加一个样式……

回答：原来用纯 CSS是表达不了（CSS3没有父元素选择器）；
不过 CSS4更新了功能，可以参考 CSS4选择器文档CSS Selectors from CSS4 till CSS1
，还有这篇文档：新增伪类 :has()
语法是：
```
!li > p { border:1px solid #CCC; }  /* 为 p 的父元素 li 设置一个边框 */
```
注意的是，这样的父级选择器当时一直都没有被各大浏览器支持；但是可以试试。

标签: css
问题：微信小程序的背景图要怎么显示？
开发小程序的时候，设置页面的背景，我用到css代码：
```
.page__bd{
    width: 100%;
    height: 220px;
    background: url('../../assets/img/images.jpg') no-repeat;
    background-size: 100% 100%;
}
```
在调试工具上是显示的，但是扫面上传到手机上却显示不出来，谁遇到过这样的问题？

回答：可以用行内来实现
```
<view class="warp" style="background-image: url('../../images/welcome.png')">

</view>
```
上面这个在“开发工具”中能显示，但是用手机预览的时候就不出图，所以下面：
以欢迎页面来说：
wxml:
```
<!-- welcome.wxml -->
<view bindtap="goHome" class="warp">
    <image src="../../images/welcome.png"></image>
    <text>{{ countDownNumber }}</text> <!-- 倒计时 -->
</view>
```
css:
```
page {
    height: 100%;
}
.warp {
    height: 100%;
    position: relative;
}

.warp image {
    width: 100%;
    height: 100%;
}

.warp text {
    width: 20px;
    height: 20px;
    line-height: 20px;
    text-align: center;
    color: #fff;
    position: absolute;
    top: 46%;
    left: 50%;
    margin-top: -10px;
    margin-left: -10px;
    border-radius: 50%;
    background-color: rgba(0,0,0,.5)
}
```
js:
```
//welcome.js
//获取应用实例
const app = getApp();

Page({

    /**
     * 页面的初始数据
     */
    data: {
        countDownNumber: 5,
        timerId: 0
    },

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad: function (options) {
        var page = this;

        //倒计时关闭当前页，重定向到首页
        var timer = setInterval(function(){
            page.setData({
                countDownNumber: page.data.countDownNumber - 1
            });
            if (page.data.countDownNumber == 1) {
                clearInterval(timer);
                wx.switchTab({
                    url: '../index/index'
                })             
            }            
        },1000);
        page.setData({
            timerId: timer
        })
    },

    /**
     * 触击“欢迎页面”直接重定向到首页
     */
    goHome: function(e){
        //清空计时器
        clearInterval(this.data.timerId);
        //关闭当前页，重定向到首页
        wx.switchTab({
            url: '../index/index'
        })
    }

})
```
这么着“开发工具”与预览都没问题，线上没试过，它这css里好像只能放网络地址...，我也是头一次摸....

标签: 微信小程序
问题：vue2 如何去除带__ob__这样的数据？
```
data: function () {
    return {
        cityData: cityData,
        selectedOptions:this.source[this.schema_key]
    }
}
```
console上面的this.source[this.schema_key]如下
```
[24, 81, __ob__: Observer]
```
有么有一种方式可以直接这样获取这样数据
```
[24, 81]
```

回答：`__ob__: Observer`这些数据是vue这个框架对数据设置的监控器，一般都是不可枚举的。
`console.log`这样的打印函数，被打印的变量会执行自身的`toString()`，这样，即便内部属性是不可枚举，实际上也能看到。举个例子：
```
const obj = {
    a: 0,
    b: 1
};
Object.defineProperty(obj, 'b', {
    writable: false,
    enumerable: false,
    configurable: false
});

console.log(obj);    // Object {a: 0, b: 1}
```
因为你已经将数据绑定在了vue之中，vue就肯定要为数据添加监控器的，如果你强制删掉了这些监控器，那么这些数据也就失去了监控，那么你使用vue的意义何在……
如果仅仅是去掉这些监控器而不考虑后果的话，把对象复制一份就行了，因为复制的对象是不包含不可枚举属性的。
```
const obj1 = {
    a: 0,
    b: 1
};
Object.defineProperty(obj1, 'b', {
    writable: false,
    enumerable: false,
    configurable: false
});
const obj2 = Object.assign({}, obj1);

console.log(obj2);    // Object {a: 0}
```
js这类动态语言，复制对象是个很头疼的事情。我写了个简单的，你可以参考一下：
```
//对象深复制，不考虑循环引用的情况
function cloneObj(from) {
    return Object.keys(from)
        .reduce((obj, key) => (obj[key] = clone(from[key]), obj), {});
}
//数组深复制，不考虑循环引用的情况
function cloneArr(from) {
    return from.map((n) => clone(n));
}
// 复制输入值
function clone(from) {
    if (from instanceof Array) {
        return cloneArr(from);
    } else if (from instanceof Object) {
        return cloneObj(from);
    } else {
        return (from);
    }
}

const obj = [
    {
        name: '1'
    },
    {
        name: '2'
    }
];
const obj2 = clone(obj);
console.log(obj2);
```
在外面直接用`clone()`方法就行了。

标签: javascript
问题：php new 一个类 比如$a = new Cat(); Cat后面为什么写()而不是{}
<?php
```
class Cat{
    public $name;
    public $age;
    function __construct($name,$age){
        $this->name = $name;
        $this->age = $age;
    }
}
$a = new Cat('小白',2);
为什么new Cat('小白',2) Cat后面是()而不是{},看起来很像是函数调用啊,虽然new一个
对象,构造函数会自动调用
因为js里面没有类,只有构造函数,所以new方式调用函数很好理解!
```
?>

回答：首先`new xxx()`这是规定的声明类的写法，至于你说像函数调用，其实你也可以理解成在`new Cat('小白', 2)`的时候调用了`class Cat`中的构造函数`__construct()`，并且传递了两个参数

标签: php
问题：提高InnoDB导入数据的速度
向mysql中导入维基百科的数据（数据源中sql的部分,总数据20g，单条sql 100MB--5GB），导入速度太慢，1个晚上才导入不到1GB，如何提高导入速度。主键唯一性检验和自动提交都已经关了。

回答：之前回答过一个类似的问题，思路如下：
对于insert方式写入优化点：
1、insert批量执行，禁止单条insert value（注意单条sql长度限制，可临时调整max_allowed_packet）
2、开启事务处理，批量提交。原理类似上1(条件允许可适当增大innodb_log_buffer_size，增加单事务提交日志量，该参数read only)
3、主键顺序插入，效率更高
4、业务允许，暂时disable keys
其他录入方式，比如load data是比较快的，可以试试
另外如果业务允许，暂时禁用binlog，并将redolog文件采用软连接的方式放入内存减少磁盘io（同样也可以把你的表数据文件放入内存目录/dev/shm，要求内存足够），要记得导入完成重新放入磁盘，以上两种方式导入均可采用此方式减少磁盘io

标签: 数据库, mysql, innodb
问题：.vue文件中 使用@import 来导入样式的路径问题
```
    <style  lang="stylus">
        //使用 ../来匹配路径可以正确导入
        @import '../assets/css/main.styl'; //正确
        //使用 alias 中 配的 @ 就不能用了
        @import '@/assets/css/main.styl';  //错误
    </style>
```
怎么解决这个 @import 导入css文件的路径问题的 
总不能一直 ../ 吧、
webpack 配置的 alias 好像不能作用在css里面里面
大佬们有什么解决办法吗？？

回答：eg: 
@import '~@/assets/scss/helpers/_mixin';
使用 ~
原理：
CSS loader 会把把非根路径的url解释为相对路径， 加~前缀才会解释成模块路径。

标签: vue.js
问题：PHP二维数组根据键值对获取一组数组 (不使用foreach)
```
$user = array(  
    0 => array(  
        'id'    => 1,  
        'name'  => '张三',  
        'email' => 'zhangsan@sina.com',  
    ),  
    1 => array(  
        'id'    => 2,  
        'name'  => '李四',  
        'email' => 'lisi@163.com',  
    ),  
    2 => array(  
        'id'    => 5,  
        'name'  => '王五',  
        'email' => '10000@qq.com',  
    ),  
    ......  
); 
```
比如我想获取当id=2时,该数组的全部内容,不使用foreach,在PHP 5.3版本下

回答：```
$user = array(  
    0 => array(  
        'id'    => 1,  
        'name'  => '张三',  
        'email' => 'zhangsan@sina.com',  
    ),  
    1 => array(  
        'id'    => 2,  
        'name'  => '李四',  
        'email' => 'lisi@163.com',  
    ),  
    2 => array(  
        'id'    => 5,  
        'name'  => '王五',  
        'email' => '10000@qq.com',  
    )
);
$ids = array_column($user, 'id');
$new_user = array_combine($ids, $user);
var_dump($new_user[2]);
```

标签: php, 二维数组, 循环
问题：vue for循环内点击只显示当前的
拿到了后台给的数据，在循环的时候添加的click，想在点击当前td的时候改变当前下面的show，而不是所有
```
<tr v-for='(i,index) in data'>
    <td @click="changeData">
      <div v-if="show">{{i.mobileNumber}}</div>
    </td>
    <td></td>
    <td></td>
    <td></td>
</tr>


```
我想过在拿到后台数据以后自己给每条数据加个show:false,但有没有更好的方法

回答：再添加一个数据项
```
currentActive: -1
```
td设置
```
@click="currentActive = index"
```
然后div设置
```
v-if="currentActive == index"

```
相当于一个游标，指向当前激活数据。

标签: vue.js
问题：js = ==赋值判断问题
1.无意间发现的一个问题 知道语法错误 但不知道原理是为什么.为什么bool打印出来是false
2.var bool,bool_;
if(bool=true && bool_==false){}
console.log(bool,bool_);//false undefined

回答：很简单， js 运算符优先级的问题， && 的优先级比 = 的要高，所以你这样写等于
```
var bool,bool_;
if(bool=(true && bool_==false)){}
console.log(bool,bool_);//false undefined
```
这样写即可得到想要的结果
```
var bool,bool_;
if((bool=true) && bool_==false){}
console.log(bool,bool_);
```
望采纳！

标签: javascript
问题：小程序标记点（markers）怎么保持在地图中间?
组件：https://mp.weixin.qq.com/debu...
API:https://mp.weixin.qq.com/debu...
效果就像滴滴出行的地图，可以进行选点，让标记（markers）一直居中，用户滑动放手后，获取地图中心点坐标

回答：标记marker可以用control来做，将这个control定位在地图中间就行；
放手后获取地图中心坐标需要用regionchange，他可以判断当前对地图的操作状态，当e.type为end时用mapContext 获取到地图中心的位置；
相关文档：https://mp.weixin.qq.com/debu...
https://mp.weixin.qq.com/debu...

标签: javascript, 小程序
问题：Python requests.get 爬虫 设置代理 IP地址未改变
工作需要爬取亚马逊上面的信息，但是亚马逊反爬虫太厉害，同一个IP地址会被封。
Python版本：3.6， IDE：Pycharm 2017.1
在网上查了很多资料，requests库的手册也读过，但是都是同一个方法，代码如下：
```
import requests
'''代理IP地址（高匿）'''
proxy = {'HTTPS': '117.85.105.170:808'}
'''head 信息'''
head = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36', 
    'Connection': 'keep-alive'}
'''http://icanhazip.com会返回当前的IP地址'''
p = requests.get('http://icanhazip.com', headers=head, proxies=proxy)
print(p.text)
```
根据我看过的许多教程的理论，如果代理设置成功，最后显示的IP应该是代理的IP地址，但是最终还是我真实的IP地址，这样一来不就等于没有设置代理么？

回答：proxies在你访问http时用http的设置，访问https时用https的设置
所以你的proxy需要同时包含http及https的配置，这样才能生效
```
proxy = {
    'http': 'http://117.85.105.170:808',
    'https': 'https://117.85.105.170:808'
}
```

标签: 网页爬虫, python
问题：express app和router的区别
var app = express(); 
var router = express.Router();
以上二者的区别是什么，什么时候用哪个最合适

回答：区别看下面的例子：
app.js
```
var express = require('express'),
    dogs    = require('./routes/dogs'),
    cats    = require('./routes/cats'),
    birds   = require('./routes/birds');

var app = express();

app.use('/dogs',  dogs);
app.use('/cats',  cats);
app.use('/birds', birds);

app.listen(3000);
```
dogs.js
```
var express = require('express');

var router = express.Router();

router.get('/', function(req, res) {
    res.send('GET handler for /dogs route.');
});

router.post('/', function(req, res) {
    res.send('POST handler for /dogs route.');
});

module.exports = router;
```
在 `app.js` 中调用 `express()` 时，返回一个 `app` 对象。
`app` 对象可以看作创建了一个 `Express` 应用程序。
而当 `express.Router()` 被调用时，返回稍微不同的“迷你应用”。
“迷你应用程序”背后的想法是，应用程序中的不同路线可能变得相当复杂，你可以从将该逻辑移动到单独的文件中获益。
在上面这个简单的例子中，`/dogs` 路由的逻辑已经被移动到自己的文件中，所以它的 `GET` 和 `POST` 处理程序不会混乱 `app.js`。
现在，你可以独立地处理对 `/dog` 的任何请求的逻辑，而不用担心它将如何影响猫 `/birds`。
如果你具有与所有三条路由相关的逻辑（`Express` 中称为中间件），则可以将其放在 `app.use(...)` 调用上方的 `app.js` 中。
如果你有逻辑仅与其中一条路线（`/dog`）相关，那么你只将它放在该路由的文件中。
以上回答，来源于Differences between express.Router and app.get?
共同学习，给赞更好～～～
至于什么时候使用，其实上面的例子已经解释了。
如果代码非常简单，完全可以 `app.get('/',....)`,如果路由比较复杂，使用 `express.Router()` 更合适。

标签: express, nodejs-express, javascript
问题：为什么JAVA很多类都放弃了安全而要速度呢
比如hashmap和hashtable，arrylist和vector这种的，我学的时候都说是xxx不用了，区别是一个安全一个不安全，当然hashtable那个还有个null的区别，为啥要用不安全的呢

回答：什么叫`放弃安全而要速度`。
这认识错的太远了，需要线程安全的情况下当然是`必须`要使用线程安全的类型了，不需要自然是可以不用使用了。
如下代码
```
public void m() {
    int i = 0;
    String s = "string" + i;
    System.out.println(s);
}
```
`JDK`会将字节码编译成如下
```
  public void m();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: iconst_0
         1: istore_1
         2: new           #2                  // class java/lang/StringBuilder
         5: dup
         6: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
         9: ldc           #4                  // String string
        11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        14: iload_1
        15: invokevirtual #6                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        18: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        21: astore_2
        22: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
        25: aload_2
        26: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        29: return
```
可以很清楚的看到字节码中将字符串连接编译成`StringBuilder`的方式，我们知道`JDK`还提供了一个`StringBuffer`线程安全的字符串操作类。那`JDK`编译时为什么不选择`StringBuffer`来做呢，答案很显然是`不需要`，因为这是在一个方法的内部，一个`局部变量`是不可能会遇到`线程安全`问题的。
而`HashMap`与`HashTable`也是同理，如果你是`局部变量`那只需要选择`HashMap`就可以了。如果是`全局变量`且会有多个线程同时操作该变量的情况当然是不能选择`HashMap`，而是要选择`HashTable`这种线程安全的类型，但是现在`HashTable`被选择的也会很少是因为有了更好的选择如`ConcurrentHashMap`来代替。

标签: java
问题：如何让不带www的网站访问时跳转到带www的网站
我用的是nginx,我按照网上说的301配置但是没有效果，有没有懂的麻烦给讲解一下

回答：基于域名的虚拟主机的虚拟主机可以轻松做到这一点。
```
server {
    server_name example.com;
    return 301 $scheme://www.example.com$request_uri;
}

server {
    server_name www.example.com;
    #... SNIP ...#
}
```

标签: php, nginx
问题：PHP有办法在闭包外部得到闭包内部的变量吗？
```
<?php


 $arr = [
     ['2','3'],
     ['6,7']
 ];
 

     $s= array_walk($arr, function($_value,$_key){

           $a = 10;

           return true;
   });

     var_dump($a);//$a 打印的时候报错了，如何得到$a呢？
```

回答：```
<?php

$arr = [
    ['2','3'],
    ['6,7']
];
$a = 0;
$s = array_walk($arr, function($_value,$_key) use (&$a) {
   $a = 10;

   return true;
});

var_dump($a);
```

标签: php
问题：三个函数调用之后分别输出什么？
下面的三个函数调用之后分别输出什么？
```
function f1(x, y, a) {
    arguments[2] = 10;
    console.log(a);
}
f1(1, 2, 3);

function f2(x, y, a) {
    arguments[2] = 10;
    console.log(a);
}
f2(1, 2);

function f3(x, y, a) {
    arguments[2] = 10;
    console.log(arguments[2]);
}
f3(1,2);
```
求分析:
输出结果：第一次：10；第二次：undefined；第三次：10

回答：- arguments是伪值，它是传入函数参数的值组成的数组，它的顺序和参数列表一致，且可以在函数内被重写
- arguments中，每一个值都是指向参数本身的内存，而并非是副本
- 函数内`arguments`，其实就是取到了`[x, y, a]`
- 其中，`arguments[2]`对应的是`a`，且直接指向`a`的内存
- 因此，第一个函数输出10，因为修改`arguments[2]`也就是修改`a`的内存，也就是对`a`赋值10
- 第二次，由于没有传`a`，所以`arguments[2]`没有指向任何内存，且`a`也没有指定内存，因此是`undefined`
- 第三次，由于`arguments[2]`没有指向任何内存，`a`也没有指定内存，所以，`arguments[2]`实质是给`arguments[2]`开辟了一块内存，并初始化值为10，但是这块内存并不是`a`的内存

arguments是伪值，它是传入函数参数的值组成的数组，它的顺序和参数列表一致，且可以在函数内被重写
arguments中，每一个值都是指向参数本身的内存，而并非是副本
函数内`arguments`，其实就是取到了`[x, y, a]`
其中，`arguments[2]`对应的是`a`，且直接指向`a`的内存
因此，第一个函数输出10，因为修改`arguments[2]`也就是修改`a`的内存，也就是对`a`赋值10
第二次，由于没有传`a`，所以`arguments[2]`没有指向任何内存，且`a`也没有指定内存，因此是`undefined`
第三次，由于`arguments[2]`没有指向任何内存，`a`也没有指定内存，所以，`arguments[2]`实质是给`arguments[2]`开辟了一块内存，并初始化值为10，但是这块内存并不是`a`的内存

标签: javascript