在实现之前呢,我们首先要知道 bind 是做什么的。JS MDN 给出的定义是 The bind() methods creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called. ,简单来说就是 bind() 函数创建了一个新函数(原函数的拷贝),这个函数接受一个提供新的 this 上下文的参数,以及之后任意可选的其他参数。当这个新函数被调用时,它的 this 关键字指向第一个参数的新上下文。而第二个之后的参数会与原函数的参数组成新参数(原函数的参数在后),传递给函数。
Vuex 使用了单状态树(single state tree),一个 store 对象就存储了整个应用层的状态。它让我们可以更方便地定位某一具体的状态,并且在调试时能简单地获取到当前整个应用的快照。
先埋个伏笔。Vuex 使用的这种 single state tree 与 modularity 模块化是不冲突的,问题是,如何将 state 与 mutation 分到子模块中?
要使用 store ,首先必须Vue.use(Vuex),然后将 store const store = new Vuex.store() inject 定义到 Vue 实例 app 中new Vue({store}),实现从根组件注入到所有子组件中,接着就可以在子组件中使用 this.$store 调用了。
三者的联系就在于,都可以用来改变函数中 this 指向的值,且第一个参数为要指向的 this 的值,apply的第二个参数(或 bind 与 call 的不定参数)为要传入的参数。这就不得不提及 javascript 中函数的 this 的指向了。this 的指向大概有以下几种。
1.全局作用域下或正常的函数调用的 this 此时 this 指向的是全局对象。这时有两种情况,如果是在浏览器环境下运行,则 this 指向全局的 window 对象;而如果是在 nodejs 环境下执行,命令行中指向的是 global 对象。有一点需要注意的是,严格模式 “use strict” 下的 this 为 undefined 。
1
2
3
// 浏览器
this.a = 10;
console.log(window.a); // 10
1
2
3
// nodejs
this.a = 20;
console.log(global.a); // 20
1
2
3
4
5
6
// 非严格模式
functionf1(){
returnthis;
}
console.log(f1() === window); // 浏览器 true
console.log(f1() === global); // nodejs true
1
2
3
4
5
6
// 严格模式下
functionf2() {
"use strict";
returnthis;
}
console.log(f2() === undefined); // true
2.当函数作为某对象的方法被调用时 this 指向的是调用该函数的对象,以下代码指的是对象 a。
1
2
3
4
5
6
7
var a = {
b: 30,
c: function () {
console.log(this.b);
}
}
a.c(); // 30
3.构造器函数调用 以构造器函数的形式声明函数,再用 new 关键字声明一个新的函数对象,此时函数中的 this 指向这个构造出来的对象。在 jslint 比较严格的要求下,这种构造函数的函数名必须是首字母大写的形式。
1
2
3
4
5
functionA() {
this.b = 40;
}
var obj = new A();
console.log(obj.b); // 40
4.利用 apply/call/bind 方法强制改变 this 的指向 这时可以将要指向的对象 O 作为第一个参数传给以上任意三个函数之一,用某 F 函数调用这三个函数,这样 F 函数中的所有 this 的指向就都变成了对象 O,并且此时 O 就算没有声明 F 函数中的方法,也可以正常调用 F 函数中的方法。