且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

javascript - 问一个JS继承的问题

更新时间:2022-11-09 13:39:50

首先是箭头函数内部 this 指向的问题,
箭头函数内部本身没有 this ,内部 this 只能通过作用域链往上查找.
所以

Tree.prototype.addLeaf = () => {this.leaf++}

这里的 this 指向 window.

然后...没时间了, 领导要我打扫办公室卫生. 下面这个 demo 你先看着. 等会回来再说..
https://jsfiddle.net/pqjag5vj/

OK, 回来了, 题目也改了

Tree.prototype.addLeaf = function () {
    this.leaf++
}
tree1.addLeaf()
tree1.addLeaf()

说说执行 tree1.addLeaf() 这句代码的时候发生了什么,
JS 函数内部 this 指向只有在调用的时候才确定,
那么, tree1 调用 addLeaf 的时候, addLeaf 内部 this 是指向 tree1 的.
也就是说,执行 tree1.addLeaf() , addLeaf 函数其实相当于

function () {
    tree1.leaf++
}

然后就是实例属性与原型属性同名问题.
虽然可以实例可以通过原型链访问到原型中的值, 但是不能通过对象实例重写原型中的值.
所以, tree1.leaf 中的 leaf 就是在实例上创建的属性, 后面执行 tree1.addLeaf 的时候修改的也是 tree1 上的 leaf 属性, 并非原型上的 leaf 属性.

当 tree2 访问 leaf 属性的时候, 还是按照原型链往上找,
原型上的 leaf 并没有给修改, 所以还是 0.

那么, 我们怎么修改得让它符合预期, 使他修改原型上的属性呢, 一种是我上面给出的 demo , 通过 proto 对象实例的属性(它指向对象构造函数的原型对象) 来访问并修改原型上的属性.
还有通过apply, bind, call 等方法, 把 addLeaf 的 this 绑定到希望的原型对象上.