关于js的原型的一个问题

2014-01-23 22:00:48 +08:00
 Tankpt
先附上一段代码
function fTest(name){}

fTest.prototype.name = "hello";

fTest.prototype.setname = function(name){
this.name = name;
};

fTest.prototype.getname = function(){
console.log(this.name);
};

var oTest1 = new fTest();
var oTest2 = new fTest();

oTest2.__proto__ === oTest1.__proto__;//返回true


然后就是我查看了下oTest1中的属性,发现有name,一点疑问,我之前对他的理解都是fTest.prototype.name = "hello";,这句话表明在fTest.prototype中有一个变量为name,然后oTest1和oTest2全部指向他,我的理解是两个共有的一个属性,只要在一个改变了,那另一个去访问也会变化,但是我实际看了下在OTest1对象中有name,这个我在function fTest(name){}中又没进行申明,为啥有这个属性呢?

我的一点怀疑是不是我这个东西的this出了问题,有点乱指了,一点感觉不知道对不对,还望前辈们指点下问题
3272 次点击
所在节点    问与答
28 条回复
otakustay
2014-01-24 02:34:38 +08:00
js找属性的逻辑很简单:
1. 自己有没有这属性,有的返回
2. 原型有没有这属性,有的返回
3. 原型的原型有没有这属性,有的返回
4. 如果原型的原型的...的原型不存在,返回个undefined

js写属性的逻辑更简单:直接往上面写,和原型没关系

然后你的代码:
1. oTest1和oTest2共享一个原型,这个无误
2. 在没有调用setName前,找oTest1的name找到的是原型上的,oTest2的name也是原型上的,他们一样
3. oTest1.setName('hello')后,oTest1的name找的是自己的,这是上面说的步骤的第1步。而oTest2找name是原型上的,是上面的第2步。因此它们返回的东西不一样,且你能看到oTest1有name了

至于你说的oTest1的name变了oTest2会变,这个显然是错的,根据上面找属性的步骤来看,oTest1.setName('hello')改的是oTest1上的东西(在原型的前面),导致原型上的那个name在oTest1读取时被“隐藏”起来了,但仅仅是隐藏,其值是没有被改动的。
otakustay
2014-01-24 02:40:56 +08:00
至于this更简单,就是4种调用方法来决定this是啥
我想说js其实没有任何难的,无论是this还是原型链还是作用域链,统统简单的要死,根本就是一帮半调子开发者自己玩不出来就到处说这难那难,把人吓得看一眼就觉得复杂没敢认真去理解
给你看一下我讲课和技术分享时用的一些PPT:https://www.dropbox.com/sh/alem0za5y1y53j4/DpqaYZJeIn
其中的Brief Javascript.pptx就是js的入门课程,虽然没有对应的讲述会稍微有些难理解,不过你可以看一下,关于原型、作用域、this在这里面都有讲到,我认为这个PPT上的东西都能理解的话,js就算入门了
想继续深入的可以看所谓闭包.pptx,和闭包、作用域链有关的概念这里面应该全讲清楚了,再往下可以看Inside the browser.pptx和异步编程与浏览器执行模型.pptx,这是浏览器底下的知识了
sd4399340
2014-01-24 10:15:08 +08:00
Tankpt
2014-01-24 11:20:02 +08:00
otakustay
2014-01-24 11:44:27 +08:00
@sd4399340 我自己能打开,搞不懂dropbox,给一个skydrive的吧不过可能版本有些老,错误倒是没有:https://skydrive.live.com/redir?resid=556CE34496EA9887%21105
FrankFang128
2014-01-24 12:43:07 +08:00
@otakustay 对啊,JS最难的地方其实在于“怎样用C++/Java/C#的思维方式来思考JS”,可惜很多半路转职的开发者在这一点上越陷越深。


@Tankpt 不错,都是对的。不过我觉得图画得太复杂了。“对象的 __proto__ 指向它构造函数的 prototype”这一句话就能解释那几张图了。

oTest1 是个对象,那么它的 __proto__ 指向构造函数 fTest 的 prototype;
构造函数 fTest 的 prototype 也是个对象,其 __proto__ 指向构造函数 Object 的 prototype;
依此类推。
Tankpt
2014-01-24 14:17:17 +08:00
@FrankFang128 恩恩。那个图么。就是感觉这么画出来直观点。我怕自己解释不清,哈哈。我刚又看了一遍你们的回复,明白多了。灰常感谢
Tankpt
2014-01-25 16:26:47 +08:00
@FrankFang128 不晓得论坛里怎么私信,今天对那个constructor对象有点疑问了,主要是在实现继承的过程中,发现contructor指向了父类的构造函数,这个从面向对象的理解上,我觉得没问题,就是在实现上有点疑惑,不晓得在哪里改动了,或者说这个constructor属性是在什么情况下会修改,就比如下面的这个段代码
function SuperType(){
this.name ="person";
}

SuperType.prototype.getname = function(){
console.log(this.name);
};

function Subtype(){
this.name = "man";
}

Subtype.prototype = new SuperType();

在Subtype.prototype 中的constructor指向了SuperType,我的理解这个不是应该指向subtype么

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/98150

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX