js继承学习笔记

由一段代码印发的思考

function A(){}
var a = new A();
A.prototype = {x:3};
console.log(a.x);

想一下这段代码会输出什么,会输出3么,如果你的答案是3,那么恭喜你,下面的东西也是你需要的。

首先,正确的答案是undefined,不相信可以在控制台输出一下,结果一定是undefined,也就是说,a中并不存在一个 x属性,如果我们将代码改成这样,再看看结果是什么样子的:

function A(){}
var a = new A();
Object.prototype.x=3;
console.log(a.x);

这次再试一下,你会发现输出了3,是否找到问题了呢?

当我们在创建一个构造函数,也就是function A的时候,虽然没有规定他的prototype属性,但是JavaScript中明确指出,没一个JavaScript对象都和另一个对象关联,就是原型,换句话说,每一个JavaScript对象都有原型,那就证明A也是有原型的,而且原型值指向Object对象。

所以,当我们实例化一个A的对象a的时候,a会继承A的属性,而A的属性中并不存在自有属性,所以A的属性实际上就是继承自Object,因此,a的原型是指向Object的。

第一段代码,a的原型指向Object,这时我们设置A的prototype,也就是改变了A的原型,但是之前实例化的a的原型并没有继承A的属性,而是直接指向了Object,所以并不会受到影响。而Object的属性中也没有一个属性是x,JS中使用一个不存在的属性会返回一个undefined。

第二段代码,我们直接给Object的prototype添加一个x的属性,此时在a中就可以拿到x属性的值了。

如果我们将第二段代码中的

Object.prototype.x=3;

替换成

Object.x=3;

你会发现还是会输出同样的结果,其实js的继承,只有在查询属性的时候才会体现出来,查找一个对象的属性的时候,先会在对象的自有属性中进行查找,如果有就直接返回,如果没有会在对象的原型中查找,如果原型中也没有找到,就在原型的原型中查找,,,,这样传说中的原型链也就形成了。

有些时候我们在使用new方法创建对象的时候,比如new Date()这样的方式创建的对象,他的prototype指向的是DDate对象,而Date的prototype也继承自Object。