是否能将对象作为原型?


是否能将对象作为原型?

使用Baby初始化child


使用Baby初始化child

apply和call方法


apply和call方法

Child原型链的形成


Child原型链的形成

代码和解释部分


**HTML:**

1. <!DOCTYPE html>
2. <html>
3.
4. <head>
5.     <meta charset="utf-8">
6.     <title>原型链</title>
7.     <script src="Baby.js"></script>
8.     <script src="child.js"></script>
9.     <script src="Student.js"></script>
10.     <script src="work.js"></script>
11.     <style>
12.
13.     </style>
14. </head>
15.
16. <body>
17.     <script>
18.         var baby = new Baby('wangzihao', true, new Date(2014, 5, 1, 12, 0, 0))
19.         console.log(baby)
20.         baby.eat('苹果')
21.         console.log(baby.getAge())
22.         baby.sleep(12)
23.         baby.name = '123456'
24.         baby.age = 13
25.
26.
27.         console.log(baby)
28.         var child = new Child('liquanfu', true, new Date(2013, 5, 1, 12, 3, 3))
29.         // child.eat('ff')
30.         console.log(child)
31.         child.play('堆积木', 8)
32.
33.         var student = new Student('小王', true, new Date(2013, 5, 1, 12, 3, 3))
34.         console.log(student)
35.         student.eat('螃蟹')
36.         student.play('lol', 12)
37.         student.study('HTML', 24)
38.
39.         var worker = new Worker('王军', true, new Date(2013, 5, 1, 12, 3, 3))
40.         worker.eat('手抓饼')
41.
42.         worker.study('lol', 24)
43.         worker.work('写代码', 38)
44.         worker.play('lol', 24)
45.
46.         console.log('-'.repeat(30))
47.
48.         console.log(worker instanceof Worker)
49.         // worker对象 是Worker构造函数的一个实例
50.         console.log(worker instanceof Student)
51.         console.log(worker instanceof Child)
52.         console.log(worker instanceof Baby)
53.         console.log(worker instanceof Object)
54.         // worker对象也是Student Child Baby Object构造函数的实例
55.
56.         console.log(student instanceof Worker)
57.         console.log(student instanceof Student)
58.         // student 对象不是Worker构造函数的实例
59.
60.         // 一个worker对象能否当成一个student对象来使用呢?
61.         // 一个worker对象能否当成一个child对象来使用呢?
62.         // 在语法上完全可以把worker对象当成student或者child来使用
63.         // 因为worker具有student和child所具有的所有属性和方法
64.         // 在语义上可能会有所不同 比如worker的play方法与child的play方法是不一样的
65.
66.         console.log(typeof worker)
67.         console.log(typeof student)
68.
69.         // 如果你想得到一个构造函数怎么办?
70.         console.log(worker.constructor)
71.         // 得到一个构造函数 并不是构造函数的名字
72.
73.         // console.log(worker.constructor.name)
74.         var code = worker.constructor.toString()
75.         console.log(code)
76.         var index = code.indexOf('(')
77.         console.log(index)
78.         var name = code.substring(9,index)
79.         console.log(name)
80.
81.         var worker1 = Object.getPrototypeOf(worker)
82.         var worker2 = Object.getPrototypeOf(worker1)
83.         var worker3 = Object.getPrototypeOf(worker2)
84.         console.log(worker3)
85.         // Object.getPrototypeOf() 可以获取指定对象的原型
86.
87.         console.log(worker3.isPrototypeOf(worker))
88.         // 判断一个对象是否在指定对象的原型链中
89.         console.log(child.isPrototypeOf(worker)) //false
90.         // 在搭建worker构造函数的原型链时根本没有使用child对象
91.         // 而是使用child构造函数的原型
92.
93.     </script>
94. </body>
95.
96. </html>

**Baby.js**

1. function Baby(name,isMale,birthDate){
2.     this.name = name
3.     this.isMale = isMale
4.     this.birthDate = birthDate
5.     Object.freeze(this)
6. }
7. Baby.prototype.eat = function(food){
8.     console.log(this.name + '喜欢吃' + food)
9. }
10. Baby.prototype.sleep = function(hours){
11.     console.log(this.name + '睡了' + hours +'个小时')
12. }
13. Baby.prototype.getAge = function(){
14.     return new Date().getFullYear() - this.birthDate.getFullYear()
15. }

**child.js**

1. function Child(name,isMale,birthDate){
2.     // this.name = name
3.     // this.isMale = isMale
4.     // this.birthDate = birthDate
5.     // 能不能调用Baby的构造函数
6.     // Baby(name,isMale,birthDate)
7.     // 没有this指针 当前对象不会收到name isMale等值 而且会报错
8.
9.     // Baby.call(this,name,isMale,birthDate)
10.     Baby.apply(this,[name,isMale,birthDate])
11.     // 第一个参数决定被调用函数Baby内部的this
12.     // 其它参数是被调用函数的参数
13. }
14. // Child.prototype = new Baby()
15. // 我们只是想使用baby对象中的方法 并不是真的需要一个baby对象
16. // 而且new Baby()需要传递参数 但我们并没有参数可传
17. // Child.prototype = Baby.prototype
18. // 会导致Baby的原型和Child的原型成为同一个原型
19. // 那么当下面为child的原型添加新方法的时候 新方法也会出现在Baby中
20.
21. // 空的构造函数
22. function TemConstructor(){}
23. TemConstructor.prototype = Baby.prototype
24. var tempObject = new TemConstructor()
25. // 创建一个空白对象 这个空白对象里面什么东西都没 但它的原型和Baby原型是同一个原型
26. Child.prototype = tempObject
27. // Child的原型等于刚创建的空白对象
28.
29. Child.prototype.constructor = Child
30. // 为Child的原型添加一个constructor 指定Child的构造函数
31. // 添加之后可以方便的通过对象获取它的构造函数
32.
33. // 创建一个原型链 原型链:对象的原型是一个对象 这个对象也有原型 
34. // 这个原型也是一个对象 这个对象也是原型 这个原型也是对象.......
35. // 就构成了原型链  直到对象的原型为null为止
36.
37. // 当在一个对象上调用方法及属性时 会沿着原型链一直找 直到找到一个或是
38. // 最终找完整个原型链仍然没有找到为止
39. Child.prototype.play = function(game,hours){
40.     console.log(this.name + '玩' + game + hours + '小时' )
41. }

**Student.js**

1. function Student(name,isMale,birthDate){
2.     // 通过call方法 你可以在一个对象上调用另一个对象上的方法
3.     Child.call(this,name,isMale,birthDate)
4. }
5. Student.prototype = Object.create(Child.prototype)
6. // Object.create()可以通过你提供的原型创建一个新对象
7. // 这个对象的新原型就是create()的第一个参数
8.
9. Student.prototype.constructor =
10.
11. Student.prototype.study = function(course,hours){
12.     console.log(this.name +'学习' + course + hours + '个小时')
13. }

**work.js**

1. function Worker(name,isMale,BirthDate){
2.     Student.call(this,name,isMale,BirthDate)
3. }
4. Worker.prototype = Object.create(Student.prototype)
5. Worker.prototype.constructor = Worker
6.
7. Worker.prototype.work = function(task,hours){
8.     console.log(this.name +task + hours + '个小时')
9. }
10. // 完全重写了原型链中的一个方法
11. // Worker.prototype.play = function(game,hours){
12. //     console.log(this.name + '找一个有山有水的地方')
13. //     console.log(this.name + '玩' + game + hours + '个小时')
14. // }
15.
16. Worker.prototype.play = function(game,hours){
17.     console.log(this.name + '找一个有山有水的地方')
18.     // 可以调用原型链中的任意一个方法
19.     Child.prototype.play.call(this,game,hours)
20.     console.log('假装去玩了')
21. }