美文网首页ECMAScript 6程序员
Javascript: 当我们在重写原型链时,我们在干嘛?

Javascript: 当我们在重写原型链时,我们在干嘛?

作者: mary_s | 来源:发表于2016-04-16 22:55 被阅读205次

JS中的原型链,曾经困惑过我。理论上说,当访问一个对象的属性时,首先在本身的属性里去找,如果没有找到,就去这个对象的原型找。如果原型有,就是它了,如果没有继续在往原型的原型找下去。。。

那么问题来了,假设这里的访问是指“写属性”,在搜索这个实例对象原型的时候,咦,找到了这个属性,那么现在重写这个属性,究竟是在本实例对象内新写了这个属性,还是在原型上重写了此属性呢?

区别在于,若是在本实例对象写属性,那么虽然以后访问(不论是读还是读写)的都是本实例的该属性,但其实原型上的这个属性也并没有消失也没有改变,只是访问的时候屏蔽它了。

而若是直接改写了原型上这个属性,那么以后任何这个原型的其它实例,它们的这个属性都会改变(前提是这些实例并没有自身的同名属性)。

到底是哪种呢,我们把代码跑起来看看!

function SuperType () {    
    this.property = true;
}
SuperType.prototype.getSuperValue = function () {    
    return this.property;
};
function SubType () {    
    this.subproperty = false;
}
SubType.prototype = new SuperType();

//给新实例写方法 这方法到顶级原型都没有 所以写在新实例里面了
SubType.prototype.getSubValue = function () {    
    return this.subproperty;
}

//给新实例写方法 这方法顶级原型有 
//所以究竟是给实例添加了同名属性,还是直接改写了顶级原型??
SubType.prototype.getSuperValue = function () {    
    return false;
}
var instance = new SubType();
console.log(instance.getSubValue()); //false
console.log(instance.getSuperValue()); //false
console.log(SuperType.prototype.getSuperValue()); //undefined

undefined!!看到了没,顶级原型上的这个getSuperValue并没有被改写!如果改写了,那就是false,而不是undefined,是undefined的意思就是,还是原型的这个属性还是那个return this.property的函数,因为没有实例化,所以不存在this, 所以结果是undefined。也就是说,给对象写一个自身并不具有的属性,而原型却具有的属性,那么结果不是改变它原型对象上的改属性,而是给它自身添加了这个同名属性!原型上的该属性,并不会改变!只是在访问实例的时候被屏蔽!

最后,通过prototype其实是通过指针来继承属性,所以如果链断了,或者原型指针重新指向另一个对象,那么之前通过prototype继成的任何属性全部消失。但如果是通过contructor构造函数去实例化的对象,是没有这个问题的,因为通过constructor产生的属性,全部是副本,而不是指针。prototype可以通过指针一直引,a的prototype指向b对象,b的prototype指向c对象,而constructor也有类似这样的方法可以满足链式继成,例如a的constructor是bCon函数,而bCon函数里,调用cCon函数去call(this),即cCon.call(this)就是在这个constructor函数里面。

接下来又发生了一件怪事,以上的重写都通过"="来直接赋值,当然简洁明了,毫无疑问是真正的重写。那么有时候我们对原型上某属性值是数组,我们对它的操作又是另外一番光景了。看以下代码。

//object(o) 函数作用: 以o为原型实例化一个对象
function object(o) {    
    function F () {};    
    F.prototype = o;    
    return new F();
}
var person = {    
    name: 'Nicholas',    
    friends: ['shelby','Court','Van']
};
var anotherPerson = object(person);//anotherPerson是以person为原型的一个实例对象
anotherPerson.name = 'Greg';
console.log(anotherPerson.name); //'Greg'
console.log(person.name); //'Nicholas'

anotherPerson.friends = 'mary'; 
console.log(anotherPerson.friends); //mary
console.log(person.friends); // ['shelby','Court','Van']

anotherPerson.friends.push('Mary'); 
console.log(anotherPerson.friends); // ['shelby','Court','Van','Mary']
console.log(person.friends); // ['shelby','Court','Van','Mary']

当你给实例写新属性值,这个新属性名在实例自身上并没有,但是该实例的原型上有这个属性的时候,有以下两种情况:

  1. 这里的“写”属性,是指用''=" 赋值,其实是重新建立一个副本,那么原型上的该属性值不会改变或消失,只是实例自身拥有了这个属性,那么以后对该实例上这个属性的读写,都是发生在自身这个属性上,不涉及原型。比如上例对name属性的重写。原型中的name还是‘Nicholas’,而实例的name则是自己重写过后的值。
  2. 这里的“写”属性,是引用的方式,比如上例,使用的是anotherPerson.friends.push('Mary'); , 这里其实是使用指针,指向原型上这个属性,通过指针去重写的属性,都是指向同一个内存上的属性,并没有副本。一旦改变,所有指向它的引用,全部都会发生改变。

相关文章

  • Javascript: 当我们在重写原型链时,我们在干嘛?

    JS中的原型链,曾经困惑过我。理论上说,当访问一个对象的属性时,首先在本身的属性里去找,如果没有找到,就去这个对象...

  • JavaScript面向对象-基于组合和动态原型创建对象

    前面两篇文章我们介绍了JavaScript中原型的内存模型和原型的重写方法即注意事项。在了解原型之后,我们就可以通...

  • JavaScript原型对象与原型链

    一、前言 原型和原型链是 JavaScript中不可避免需要碰到的知识点,在刚开始学习 JS 时,原型和原型链都是...

  • JavaScript原型(二)

    原型链 在JavaScript原型(一)中,我们介绍了每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数...

  • JavaScript之原型链的解读

    在JavaScript中,原型链作为一个基础,老生长谈,今天我们就来深入的解读一下原型链。 本章主要讲的是下面几点...

  • 前端基础整理

    如何理解JavaScript原型链JavaScript中的每个对象都有一个prototype属性,我们称之为原型,...

  • JavaScript的原型到底是什么?

    在深入学习JavaScript原型这一块我们会碰到几个概念,原型,构造函数,原型链,下面就通过图解的方式来看看吧。...

  • JS中的原型链

    在了解原型链之前,我们首先理解几个概念: JavaScript内置对象 所谓的内置对象 指的是:JavaScrip...

  • JavaScript高级程序设计学习笔记之继承模式

    原型链 JavaScript的继承主要依靠原型链来实现的。我们知道,构造函数,原型,和实例之间的关系:每个构造函数...

  • (四)继承

    1.原型链 javascript中没有类的概念,需要利用原型链来模拟。我们知道,构造函数、原型对象、实例之间有如下...

网友评论

    本文标题:Javascript: 当我们在重写原型链时,我们在干嘛?

    本文链接:https://www.haomeiwen.com/subject/ojlolttx.html