yu蜀黍:class里定义函数中的this就像孤儿院里的孩子,没有归宿,却时刻等待着有人来接他,有的孩子在孤儿院建立的时候,院长就告诉他被预定了(constructor bind),而有的,只能默默等待着某一天,栅栏门外出现一对善良的夫妇来选择自己,也只有那一刻,他才能真正找到属于自己的那个家(xxx.function())。可这个世上,从来不缺少可怜人儿,他始终没有被选择,他长大了,走出了孤儿院,开始了新的生活,他没有家人,独自一人感受着这个陌生的世界,他不知道自己属于谁,或许,只要有人向他伸出手,他就会跟那人走,他想。可此刻,他只属于天地,属于宇宙,只是世上一个不为人知的个体。(function())
es6class本质上还是es5的prototype的语法糖
例:
class foo{
constructor(){
}
a(){}
b(){}
}
// 等价于
function foo(){};
foo.prototype = {
constructor(){},
a(){},
b(){},
}
es6的class跟es5的定义方式不同
- 1.没有变量提升
- 2.this指向不同
对于第一点
test(); // 输出'test'
function test(){
console.log('test');
}
即便在定义test函数之前执行test(),也是会得到结果的。这是因为解析javascript代码的时候会把所有的function test(){}这类代码(即正常定义函数)都提升到最上方去定义。
但class会报错
let a = new test(); // 报错
class test(){}
第二点this
class Child {
saySomething() {
this.say('hello world');
}
say(text) {
console.log(text);
}
}
const child = new Child();
child.saySomething(); //输出hello world
const { saySomething } = child;
saySomething(); // !!!!!报错
// Uncaught TypeError: Cannot read property 'say' of undefined
child中saySomething函数的this原本指向的是执行环境,child.saySomething()时指向child,saySomething()指向window,所以需要绑定bind
class Child {
constructor(){
this.saySomething = this.saySomething.bind(this);
// 这里的this都是child
}
saySomething() {
this.say('hello world');
// 这里的this,
// child.saySomething();指向child,
// saySomething();指向window, bind之后一直指向child
}
say(text) {
console.log(text);
}
}
const child = new Child();
child.saySomething(); //输出hello world
const { saySomething } = child;
saySomething(); //输出hello world
借用yu蜀黍的一句话总结:
class里面的this 要区分 constructor里 还是 外。constructior里 那就是实例,外 就是 原型链。而constructor里 触发一定会构造实例,这个时候this就是对象本身。
react里面的bind(this)
react在调用render方法的时候,会先把render里的方法赋值给一个变量(比如变量foo),然后在执行foo()。
<div onClick={this.clickHandler}></div>
react构建虚拟dom,会把this.clickHandler先赋值给一个变量。假设变量clickFunc = this.clickHandler,然后把虚拟dom渲染成真实的dom,会把onClick属性值替换成onclick,并给onclick赋值clickFunc。在复杂的情况中,可能存在多次传递,如果不进行bind,那么this的指向是一定会丢失的。