js的做用域链,原型链,以及闭包函数理解

代码一:数组

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)

相关文章
相关标签/搜索