代码一:数组
this.number = 10 function a() { this.number = 20 } a.prototype.init = () => console.log(this.number) const test = new a() // 构造函数生成一个独立新对象 test.init() // 10
解析:之因此输出10,能够把 arrow function(箭头函数) 里的 this 和 arguments 关键字理解为函数做用域里的变量(由于自身没有),他访问变量沿着做用域链向上找而不是直接访问对象属性走原型链,代码中的init上头的做用域就是window,因此他的this指向window.闭包
注:能够试试把上例代码中的箭头函数换成普通匿名函数(输出就是直接走原型链访问对象属性,number = 20)app
代码二:函数
this.number = 10 function a(){ //闭包函数 return { show: () => console.log(this.number) } } a().show() // 10 函数a的this的指向window a.call({number: 20}).show() // 20 call改变了函数a的this指向,箭头函数的做用域指向改变后的函数做用域 a.call({number: 30}).show() // 30
解析:闭包函数里return出的箭头函数被调用的时候会一直引用外层函数的变量this或者arguments,因此外层函数this指向被改变,return出的箭头函数里的this也改变了.this
this的指向可理解为两大类:spa
1:test();==test.call(window,参数);//直接调用函数,this指向windowprototype
2:obj.test(); == obj.test.call(obj,参数);//函数做为对象的方法被调用,this指向该对象code
注:this指向是在被调用时分配的对象
代码三:blog
function a() { this.say = function() { console.log(1) } } a.prototype.say = function() { console.log(2) } var test = new a() test.say() // 1
只有函数有prototype,对象对应_proto_,prototype能够对主函数进行扩充,但不会覆盖主函数内的方法(若是主函数里没有此对象属性就在原型链里查找)。
简单一句话~js中访问变量沿着做用域链向上走(this),直接访问对象上的属性沿着原型链往下走~(都是就近查找哦)
对call和apply作补充:
相同点:都是为了改变对象this指向,参数二不一样:call是传进单个参数,apply是数组形式
apply能够接受一个数组或者类数组对象,console.log(...arguments) === console.log.apply(this,arguments)