代码一:
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)
代码二:
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的指向可理解为两大类:
1:test();==test.call(window,参数);//直接调用函数,this指向window
2:obj.test(); == obj.test.call(obj,参数);//函数作为对象的方法被调用,this指向该对象
注:this指向是在被调用时分配的
代码三:
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)