原型(prototype属性)和原型链。 重要!!!
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>01_原型(prototype)</title> 6 </head> 7 <body> 8 <!-- 9 1. 函数的prototype属性(图) 10 * 每个函数都有一个prototype属性, 它默认指向一个Object空对象(即称为: 原型对象) 11 * 原型对象中有一个属性constructor, 它指向函数对象 12 2. 给原型对象添加属性(一般都是方法) 13 * 作用: 函数的所有实例对象自动拥有原型中的属性(方法) 14 --> 15 <script type="text/javascript"> 16 17 // 每个函数都有一个prototype属性, 它默认指向一个Object空对象(即称为: 原型对象) 18 console.log(Date.prototype, typeof Date.prototype) //object 19 function Fun () {//alt + shift +r(重命名rename) 20 21 } 22 console.log(Fun.prototype) // 默认指向一个Object空对象(没有我们的属性) 23 24 // 原型对象中有一个属性constructor, 它指向函数对象 25 console.log(Date.prototype.constructor===Date) //true 26 console.log(Fun.prototype.constructor===Fun) //true 27 28 //给原型对象添加属性(一般是方法) ===>实例对象可以访问 29 Fun.prototype.test = function () { 30 console.log('test()') 31 } 32 var fun = new Fun() 33 fun.test() //test() 34 35 36 37 38 39 </script> 40 </body> 41 </html>
显式原型与隐式原型
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>02_显式原型与隐式原型</title> </head> <body> <!-- 1. 每个函数function都有一个prototype,即显式原型(属性) 2. 每个实例对象都有一个__proto__,可称为隐式原型(属性) 3. 对象的隐式原型的值为其对应构造函数的显式原型的值 4. 内存结构(图) 5. 总结: * 函数的prototype属性: 在定义函数时自动添加的, 默认值是一个空Object对象 * 对象的__proto__属性: 创建对象时自动添加的, 默认值为构造函数的prototype属性值 * 程序员能直接操作显式原型, 但不能直接操作隐式原型(ES6之前) --> <script type="text/javascript"> //定义构造函数 function Fn() { // 内部语句: this.prototype = {} } // 1. 每个函数function都有一个prototype,即显式原型属性, 默认指向一个空的Object对象 console.log(Fn.prototype) // 2. 每个实例对象都有一个__proto__,可称为隐式原型 //创建实例对象 var fn = new Fn() // 内部语句: this.__proto__ = Fn.prototype console.log(fn.__proto__) // 3. 对象的隐式原型的值为其对应构造函数的显式原型的值 console.log(Fn.prototype===fn.__proto__) // true //给原型添加方法 Fn.prototype.test = function () { console.log('test()') } //通过实例调用原型的方法 fn.test() </script> </body> </html>
每个函数function都有一个prototype,即显式原型(属性)
2. 每个实例对象都有一个__proto__,可称为隐式原型(属性)
3. 对象的隐式原型的值为其对应构造函数的显式原型的值
4. 内存结构(图)
5. 总结:
* 函数的prototype属性: 在定义函数时自动添加的, 默认值是一个空Object对象
* 对象的__proto__属性: 创建对象时自动添加的, 默认值为构造函数的prototype属性值
* 程序员能直接操作显式原型, 但不能直接操作隐式原型(ES6之前)
原型链
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>03_原型链</title> 6 </head> 7 <body> 8 <!-- 9 1. 原型链(图解) 10 * 访问一个对象的属性时, 11 * 先在自身属性中查找,找到返回 12 * 如果没有, 再沿着__proto__这条链向上查找, 找到返回 13 * 如果最终没找到, 返回undefined 14 * 别名: 隐式原型链 15 * 作用: 查找对象的属性(方法) 16 2. 构造函数/原型/实体对象的关系(图解) 17 3. 构造函数/原型/实体对象的关系2(图解) 18 --> 19 <script type="text/javascript"> 20 console.log(Object) //ƒ Object() { [native code] } Object函数类型 21 console.log(Object.prototype) //Object Object函数的prototype属性对应了一个Object原型对象 22 console.log(Object.prototype.__proto__) //null object原型对象没有__proto__,他就是原型对象的尽头 23 function Fn() { 24 this.test1 = function () { 25 console.log('test1()') 26 } 27 } 28 console.log(Fn.prototype) 29 Fn.prototype.test2 = function () { 30 console.log('test2()') 31 } 32 33 var fn = new Fn() 34 35 fn.test1() 36 fn.test2() 37 console.log(fn.toString()) 38 console.log(fn.test3) // undefined 39 // fn.test3() //TypeError: fn.test3 is not a function 40 41 42 /* 43 1. 函数的显示原型指向的对象默认是空Object实例对象(但Object不满足) 44 */ 45 console.log(Fn.prototype instanceof Object) // true 46 console.log(Object.prototype instanceof Object) // false 47 console.log(Function.prototype instanceof Object) // true 48 /* 49 2. 所有函数都是Function的实例(包含Function) 50 */ 51 console.log(Function.__proto__===Function.prototype) 52 /* 53 3. Object的原型对象是原型链尽头 54 */ 55 console.log(Object.prototype.__proto__) // null 56 57 </script> 58 </body> 59 </html>
原型链(图解)
* 访问一个对象的属性时,
* 先在自身属性中查找,找到返回
* 如果没有, 再沿着__proto__这条链向上查找, 找到返回
* 如果最终没找到, 返回undefined
* 别名: 隐式原型链
* 作用: 查找对象的属性(方法)
2. 构造函数/原型/实体对象的关系(图解)
3. 构造函数/原型/实体对象的关系2(图解)
面试题
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>06_面试题</title> 6 </head> 7 <body> 8 9 <script type="text/javascript"> 10 /* 11 测试题1 12 */ 13 function A () { 14 15 } 16 A.prototype.n = 1 17 18 var b = new A() 19 20 A.prototype = { 21 n: 2, 22 m: 3 23 } 24 25 var c = new A() 26 console.log(b.n, b.m, c.n, c.m)//1 undinded 2 3 27 28 29 /* 30 测试题2 31 */ 32 function F (){} 33 Object.prototype.a = function(){ 34 console.log('a()') 35 } 36 Function.prototype.b = function(){ 37 console.log('b()') 38 } 39 40 var f = new F() 41 f.a() // a() 42 f.b() //报错 43 F.a() // a() 44 F.b() //b() 45 console.log(f) 46 console.log(Object.prototype) 47 console.log(Function.prototype) 48 49 </script> 50 </body> 51 </html>
面试题1
面试题2
总结:1.每个自定义函数的原型对象是函数obj的实例化对象,每个自定义函数的原型对象的--proto--隐士属性指向函数obj的原型对象, 而OBJ的原型的--proto-- 是null
2.每个自定义函数是FUN的实例化对象
3.FUN自己new自己,他的显示和隐士原型属性指向的是他的原型对象
ES5:寄生组合式继承:通过借用构造函数来继承属性和原型链来实现子继承父
function ParentClass(name) { this.name = name; } ParentClass.prototype.sayHello = function () { console.log("I'm parent!" + this.name); } function SubClass(name, age) { //若是要多个参数可以用apply 结合 ,解构 ParentClass.call(this, name); this.age = age; } SubClass.prototype = Object.create(ParentClass.prototype); SubClass.prototype.constructor = SubClass; SubClass.prototype.sayChildHello = function (name) { console.log("I'm child " + this.name) } let testA = new SubClass('CRPER')
ES6语法: 其实就是ES5的语法糖,不过可读性很强..
class ParentClass { constructor(name) { this.name = name; } sayHello() { console.log("I'm parent!" + this.name); } } class SubClass extends ParentClass { constructor(name) { super(name); } sayChildHello() { console.log("I'm child " + this.name) } // 重新声明父类同名方法会覆写,ES5的话就是直接操作自己的原型链上 sayHello(){ console.log("override parent method !,I'm sayHello Method") } } let testA = new SubClass('CRPER')