function Person() {
this.sname = '测试' ;
this.age = 23 ;
this.sex = '男' ;
Person.prototype.say = function() {
return this.sname + ' , ' + this.age + ' , ' + this.sex ;
} ;
}
function Student() {
Student.prototype = new Person() ;
Student.prototype.constructor = Student ;
this.school = 'xxx 大学' ;
}
var stu = new Student() ;
alert(stu.__proto__) ;
alert(stu.sname) ; //undefined
为什么stu
没有继承Person
的属性呢? 只能访问自己的。 Student
的原型是[object Object], 请大家指点!谢谢大家!
1
ykjsw 2016-04-27 15:29:35 +08:00 1
第一次 var stu = new Student() ;的时候, function Student 里面的 Student.prototype = new Person() ; 还没来得及执行
你再次执行一次 var stu = new Student() ; alert(stu.__proto__) ; alert(stu.sname) ; 就是正确的了 |
2
mrsatangel 2016-04-27 15:37:04 +08:00
Student.prototype = new Person() ;
Student.prototype.constructor = Student ; 移出构造函数体内 |
3
mrsatangel 2016-04-27 15:39:37 +08:00 2
原因是执行 var stu = new Student() ;的时候在 Student 这个函数里面执行了修改 Student 的 prototype 的行为,但是这个修改不会影响当前这个 stu 对象的构造,也就是说当前的 stu 对象实际上并没有继承 Person 。再一次使用 Student 构造函数的时候所构造的实例才继承了 Person
|
4
suikator 2016-04-27 15:42:30 +08:00 via Android
这种继承写法不太好吧,万一 Person 是有参的怎么办
|
5
jsonline 2016-04-27 15:47:28 +08:00
因为链接 __proto__ 与 prototype 是构造的最后一步
|
7
palmers OP @mrsatangel 这个在哪里可以找到官方解释呢?
|
9
jsonline 2016-04-27 15:57:37 +08:00 2
|
10
learnshare 2016-04-27 16:01:01 +08:00
sex 不是性别, gender 才是;
#2 的回答比较合适,可以翻翻 JS 权威指南第 6 版,其他书里也应该有讲到类和继承的实现方式 |
12
palmers OP @learnshare 嘿嘿 随便取的 我去看看 谢谢!
|
13
sodatea 2016-04-27 16:25:16 +08:00
new 的过程
## ES5 1. new: https://es5.github.io/#x11.2.2 2. 我们只关心最后一步,调用 [[Construct]] https://es5.github.io/#x13.2.2 3. 设置 prototype 在 5-7 步,调用构造函数在第 8 步,晚于前者 ## ES2017 流程是类似的,不过用词改了很多 1. https://tc39.github.io/ecma262/#sec-evaluatenew 2. https://tc39.github.io/ecma262/#sec-ecmascript-function-objects-construct-argumentslist-newtarget 3. 设置 prototype 属性在第 5.a 步, OrdinaryCreateFromConstructor 方法 https://tc39.github.io/ecma262/#sec-ordinarycreatefromconstructor 调用构造函数是第 11 步 通俗的解释就是 MDN 上说的那些 |
15
kisnows 2016-04-27 16:50:43 +08:00
```
function Student() { Student.prototype = new Person() ; Student.prototype.constructor = Student ; this.school = 'xxx 大学' ; return Student.prototype } ``` 你可以这样改一下,虽然还是肯定不对,但是这样应该会好一点。 其实就像 2 楼说的,你新建 student 实例的时候, Student 的 prototype 上还什么都没有。你需要理解一下 new 操作符都干了哪些事情,可以看看我的这篇文章,也许可以帮助你理解。 [JavaScript 中的类和继承]( https://www.kisnows.com/2016/03/21/class%20and%20inherit%20in%20JavaScript/) |
17
SmiteChow 2016-04-27 21:42:38 +08:00
|
18
martianyi 2016-04-28 00:29:55 +08:00
es6 大法好,说实话, es5 我也不会这么写
|
19
palmers OP @SmiteChow 谢谢 提供代码实例, 但是对我来说好深奥哦~~ 我大概能理解到是使用空对象来桥接实现继承? 不知道我理解的对不对 非常感谢!!! 请问 您的链接后面 "显示 Gist 代码" 是怎么做到的? 是什么 markdown 语法
|
21
xcodebuild 2016-04-28 10:11:01 +08:00
这种写法即使写对了也有很大的隐患,例如下面的代码
function Person() { this.accounts = [] } function Student() { } Student.prototype = new Person() var a = new Student() var b = new Student() a.accounts.push({github: 'https://github.com/IAmA'}) console.log(b.accounts[0].github) // "https://github.com/IAmA" 对 a 的原型链上的引用变量进行操作时同时改变了 b 的原型链上的值 |