浅谈prototype与__proto__

其实这两个东西指向的是同一个。

对构造函数来说,它有一个prototype的对象,用来在初始化实例时往实例的__proto__对象中添加属性或者方法,对于实例来说,它有一个__proto__对象,这个对象在被该实例被初始化时被创建且从构造函数的prototype对象里继承属性或方法。

可以把从构造函数角度的prototype及从实例角度的__proto__看成是一个东西。

验证代码如下:

console.log(test.prototype===new test().__proto__)
console.log(test.prototype===new test().constructor.prototype);

结果返回都为true 注:实例的constructor指向这个实例的构造函数本身。

而__proto__对于实例本身的属性而言的逻辑为,当javascript去寻找一个实例的某个属性时,假设为a属性,如果这个实例本身有a这个属性,就会输出这个属性,如果没有,那么就会去这个实例的__proto__中去找a这个属性。

P.S 构造函数本身也可看作是一个实例。

验证代码如下:

function test(){
    this.a = ‘b‘;
};

test.prototype.a = ‘w‘;

var c = new test();

console.log(c.a)

//输出为‘b‘

解读:构造函数给实例本身添加属性a值为‘b‘,再通过构造函数的prototype为实例的__proto__添加属性a值为‘w‘,这两个同名属性都是存在的,这时输出实例c的a属性,结果为‘b‘,所以当实例本身拥有这个属性的时候,构造函数的prototype为实例的__proto__添加这个同名属性都会被无视,javascript一旦在实例本身找到这个属性就会输出而不会理会__proto__中的同名属性。

那假设在构造函数中不给实例添加这个同名属性呢。

function test(){

};

test.prototype.a = ‘w‘;

var c = new test();

console.log(c.a)

//输出为‘w‘

解读:这回我们没用通过构造函数给实例本身添加属性a,javascript在寻找实例的a属性时,在其本身没有找到,于是去它的__proto__寻找,构造函数的prototype为实例的__proto__添加了此属性,所以找到了,输出‘w‘。

验证2:从实例的__proto__属性可以改变构造函数的prototype。

验证代码:

function test(){

};

test.prototype.b = ‘w‘;

var c = new test();
var d = new test();

c.__proto__.b = ‘s‘;

console.log(c.b)
console.log(d.b)
//输出都为‘s‘

解读:构造函数prototype添加实例__proto__的属性b值为‘w‘,通过实例c的__proto__改变属性b的值为‘s‘,结果都输出为‘s‘,这就说明了,通过实例的可以改变prototype的赋值,其实若把__proto__与prototype看成是一个东西的话就好解释了,无论是通过函数的prototype还是实例的__proto__改变其中的属性及值,包括新生成实例,每一次改动后的输出值都以每次的改动为准。最后一段代码来说明这个问题。

function test(){

};

test.prototype.b = ‘w‘;

//实例c跟d
var c = new test();
var d = new test();

//实例后未做改变输出
console.log(c.b);    //输出‘w‘
console.log(d.b);    //输出‘w‘

//以实例c的__proto__修改属性b为‘s‘
c.__proto__.b = ‘s‘;

console.log(c.b)    //输出‘s‘
console.log(d.b)    //输出‘s‘

//以实例d的__proto__修改属性b为‘f‘
d.__proto__.b = ‘f‘;
console.log(c.b)    //输出‘f‘
console.log(d.b)    //输出‘f‘

//新实例一个e
var e = new test();
//很明显还是上次修改的‘f‘
console.log(e.b)    //输出‘f‘

//通过构造函数的prototype再修改为‘g‘
test.prototype.b = ‘g‘;
console.log(c.b)    //输出‘g‘
console.log(d.b)    //输出‘g‘
console.log(e.b)    //输出‘g‘

//通过实例c的constructor指向到它的构造函数再通过prototype修改为‘h‘
c.constructor.prototype.b = ‘h‘;
console.log(c.b)    //输出‘h‘
console.log(d.b)    //输出‘h‘
console.log(e.b)    //输出‘h‘
时间: 2024-11-05 13:45:42

浅谈prototype与__proto__的相关文章

浅谈prototype与__proto__、constructor三者之间的关系

1.关于prototype? a.每个函数中都有一个prototype属性,这个属性叫做原型. b.prototype指向的这个对象就叫原型对象. c.prototype表示了一个类的属性的集合. 2.原型对象中包含有constructor和__proto__. 3.当通过new将该函数实例化后,其内部方法也可用实例对象调用. 如:var ABC=new wxy(); ABC.case(); 当未被实例化时也可直接声明其内部方法调用. 如:wxy.case(); 4.我们可以通过prototyp

JavaScript中toStirng()与Object.prototype.toString.call()方法浅谈

toStirng()与Object.prototype.toString.call()方法浅谈 一.toString()是一个怎样的方法?它是能将某一个值转化为字符串的方法.然而它是如何将一个值从一种类型转化为字符串类型的呢? 通过下面几个例子,我们便能获得答案: 1.将boolean类型的值转化为string类型: console.log(true.toString());//"true" console.log(false.toString());//"false&quo

浅谈移动前端的最佳实践(转)

前言 这几天,第三轮全站优化结束,测试项目在2G首屏载入速度取得了一些优化成绩,对比下来有10s左右的差距: 这次优化工作结束后,已经是第三次大规模折腾公司框架了,这里将一些自己知道的移动端的建议提出来分享下,希望对各位有用 文中有误请您提出,以免误人自误 技术选型 单页or多页 spa(single page application)也就是我们常常说的web应用程序webapp,被认为是业内的发展趋势,主要有两个优点: ① 用户体验好 ② 可以更好的降低服务器压力 但是单页有几个致命的缺点:

浅谈javascript的原型及原型链

浅谈javascript的原型及原型链 这里,我们列出原型的几个概念,如下: prototype属性 [[prototype]] __proto__ prototype属性 只要创建了一个函数,就会为该函数创建一个prototype属性,指向该函数的原型对象.实例对象是不会拥有该属性的.默认情况下,该原型对象也会获得一个constructor属性,该属性包含一个指针,指向prototype属性所在的函数. Person.prototype.constructor===Person [[proto

浅谈JavaScript之原型

上一篇谈new关键字也是给这一篇写关于原型的文章买个伏笔,我对原型的理解可能会有偏差,如有错误,望指正一定修改,望各位道友如果想真正的理解原型的概念一定要再看完各方言论再回归教材. 言归正传谈原型,首先原型是一个对象,无论什么时候,只要创建了一个函数,就会按照规则创建一个Prototype属性,这个属性指向函数的原型对象,在默认情况下,所有的原型对象都会有一个constructor属性,这个属性又指向函数的原型对象.先来段代码 function Person(){} Person.prototy

浅谈ES6原生Promise

浅谈ES6原生Promise 转载 作者:samchowgo 链接:https://segmentfault.com/a/1190000006708151 ES6标准出炉之前,一个幽灵,回调的幽灵,游荡在JavaScript世界. 正所谓: 世界本没有回调,写的人多了,也就有了})})})})}). Promise的兴起,是因为异步方法调用中,往往会出现回调函数一环扣一环的情况.这种情况导致了回调金字塔问题的出现.不仅代码写起来费劲又不美观,而且问题复杂的时候,阅读代码的人也难以理解. 举例如下

浅谈javascript继承【读javascript设计模式第四章节继承有感】

javascript继承,无任是类式继承,原型式继承还是渗元式继承都是通过不同方法去围绕着prototype转,简单分析下三种不同继承方法是如何围绕prototype转的 一:类似继承,先上关键代码 function extend(subClass,supClass){ var fn = function(){}; fn.prototype = supClass.prototype; subClass.prototype = new fn(); subClass.prototype.constr

浅谈javascript函数劫持

http://www.xfocus.net/articles/200712/963.html 浅谈javascript函数劫持 文章提交:hkluoluo (luoluonet_at_hotmail.com) by luoluo on 2007-11-30 luoluonet_at_yahoo.cn http://www.ph4nt0m.org 一.概述 javascript函数劫持,也就是老外提到的javascript hijacking技术.最早还是和剑心同学讨论问题时偶然看到的一段代码,大

js---OOP浅谈

js---OOP浅谈 对象化编程-------简单地去理解就是把javascript能涉及到的范围分成各种对象,对象下面再次划分对象.编程出发点多是对象,或者说基于对象.所说的对象既包含变量,网页,窗口等等 对象的含义          对象可以是文字,表单等等.对象包含一下属性-------对象的某些特定的性质方法-------对象能做的事情事件-------能响应发生在对象上的事情     注意:对象只是一种特殊的数据 2.  基本对象                 我们一般划分的角度还是