prototype
__proto__
constructor
的关系
构造函数 构造函数就是提供了一个生成对象的模板并描述对象的基本结构的函数。一个构造函数,可以生成多个对象,每个对象都有相同的属性和方法。总的来说,构造函数就是对象的模板(类),对象就是构造函数的实例。同一个构造函数的生成的对象实例之间无法直接共享属性或方法。
1 2 3 4 5 function Person ( ){ this .name = 'keith' ; } var boy = new Person ();console .log (boy.name );
构造函数的特点有:
a:构造函数的函数名首字母必须大写。 b:内部使用 this
对象,来指向将要生成的对象实例。 c:使用 new 操作符来调用构造函数,并返回对象实例。
prototype
属性属性 prototype
是函数特有的属性,这个属性是一个指针,指向一个对象,这个对象的用途就是包含所有实例共享的属性和方法(我们把这个对象叫做原型对象)。通过 prototype
定义的属性及方法能被所有对象实例所共享,这就是 prototype
的意义。
对于构造函数来说, prototype
是作为构造函数的属性;对于对象实例来说, prototype
是对象实例的原型对象。
1 2 3 4 5 6 7 8 9 10 11 12 function Person (name, height ) { this .name = name; this .height = height; } Person .prototype .hobby = function ( ) { return 'watching movies' ; } var boy = new Person ('keith' , 180 );var girl = new Person ('rascal' , 153 );console .log (boy.name ); console .log (girl.name ); console .log (boy.hobby === girl.hobby );
prototype
属性的特点有:
a:原型属性 prototype
的作用,就是定义所有对象实例所共享的属性和方法。 b:prototype
对于构造函数来说,它是一个属性;对于对象实例来说,它是一个原型对象。
constructor
属性属性 constructor 返回对象实例的构造函数。
1 2 3 function Person ( ){};var boy = new Person ();console .log (boy.constructor );
constructor
属性实际上是原型对象的属性,这个属性包含了一个指针,指回原构造函数,它被所有实例对象继承。
1 2 3 4 function Person ( ){};var boy = new Person ();console .log (Person .prototype .constructor === Person ); console .log (boy.constructor === boy.prototype .constructor );
instanceof
运算符instanceof
用于判断对象是否为某个构造函数的实例。
1 2 3 4 function Person ( ) {};var boy = new Person ();console .log (boy instanceof Person ); console .log (boy instanceof Object );
__proto__
属性属性 __proto__
返回对象实例的原型对象,对象内部的 [[Prototype]]
,也即对象实例的构造函数的 prototype 属性值。使用 __proto__
是有争议的,也不鼓励使用它,因为它从来没有被包括在 EcmaScript 语言规范中,但是现代浏览器都实现了它。 ES6 中可以使用 Object.getPrototypeOf()
获取。
1 2 3 4 5 function Person (name ){ this .name = name; } var boy = new Person ('jack' );console .log (boy.__proto__ === Person .prototype );
相对于通过 __proto__
属性继承其他对象的属性而言,Object.create()
方法是一个更加值得推荐的方法。该方法接收一个对象作为参数,返回一个以该对象为原型对象的新对象,即继承了作为参数的对象的属性及方法。
1 2 3 4 5 let person = { age : 10 } let boy = Object .create (person);console .log (boy.age );
实现 子类 继承 父类 类继承的核心是让 子类 拥有 父类 的方法和属性
1 2 3 4 5 6 7 8 9 10 function Parent ( ) { this .parentAge = 50 ; } function Child ( ) {}Child .prototype = new Parent ();Child .prototype .constructor = Child ; const obj = new Child ();console .log (obj.parentAge );
1 2 3 4 5 6 7 8 9 10 function Parent ( ) { this .parentAge = 50 ; } function Child ( ) {}Child .prototype = Object .create (Parent .prototype );Child .prototype .constructor = Child ;const obj = new Child ();console .log (obj.parentAge );
实现 new new 其实就是生成了一个对象,初始化时执行类的构造函数,这个对象能够访问类的原型(属性和方法)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 function myNew (func, ...args ) { const obj = {}; let res = func.call (obj, ...args); obj.__proto__ = func.prototype ; return res instanceof Object ? res : obj } function myNew1 (func, ...args ) { let obj = Object .create (func.prototype ); let res = func.call (obj, ...args); return typeof res === 'object' ? res : obj; } function Puppy (age ) { this .puppyAge = age; } Puppy .prototype .say = function ( ) { console .log ("汪汪汪" ); } const myPuppy3 = myNew (Puppy , 2 );console .log (myPuppy3.puppyAge ); myPuppy3.say ();
实现 instanceof instanceof
作用是检查一个对象是不是某个类的实例,换句话说就是检查一个对象的的原型链上有没有这个类的 prototype
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 function myInstanceof (targetObj, targetClass ) { if (!targetObj || !targetClass || !targetObj.__proto__ || !targetClass.prototype ){ return false ; } let current = targetObj; while (current) { if (current.__proto__ === targetClass.prototype ) { return true ; } current = current.__proto__ ; } return false ; } function Parent ( ) {}function Child ( ) {}Child .prototype .__proto__ = Parent .prototype ;const obj = new Child ();console .log (myInstanceof (obj, Child )); console .log (myInstanceof (obj, Parent )); console .log (myInstanceof ({}, Parent ));