什么是原型?
javascript通过原型实现继承。每个对象都可以有一个原型,每个对象的原型也可以拥有一个原型,形成了一个原型链。查找特定属性会被委托在原型链上,按照当前对象 > 当前对象的原型 > 当前对象的原型的原型顺序查询。
· 每一个函数都有一个原型对象
· 每一个函数的原型对象都具有一个constructor属性,该属性指向函数本身
· constructor对象的原型设置为新创建的对象的原型
通过object1.prototype.xxx=function(){}设置的方法是object1的原型属性而非实例属性。
实例属性与原型属性有什么区别?
把函数作为构造函数,通过new调用,此时上下文被定义为新的对象实例,通过原型暴露属性,通过构造函数的参数进行初始化。
function Ninja(){
this.swung = false;
this.swingSword = function(){ //实例方法
return !this.swung;
};
}
Ninja.prototype.swingSword = function(){ //原型方法
return this.swung;
};
const ninja = new Ninja();
assert(ninja.swingSword(),
"Called the instance method, not the prototype method.");
若实例属性与原型属性同名,则创建新的实例对象时,实例方法会重写原型方法,在实例中可以查找到,就不会再查找原型。
7-1
原型如何实现继承?
SubClass.prototype = new SuperClass();
SubClass的实例的原型是SuperClass的实例,SuperClass实例具有SuperClass的全部属性,SuperClass实例也同时具有一个指向超类的原型。
如何解决继承后,原constructor属性被覆盖问题?
"use strict";
function Person(){}
Person.prototype.dance = function(){};
function Ninja(){}
Ninja.prototype = new Person();
Object.defineProperty(Ninja.prototype, "constructor", {
enumerable: false,
value: Ninja,
writable: true //定义一个新的不可枚举的constructor属性,属性值为Ninja
});
const ninja = new Ninja();
assert(ninja.constructor === Ninja,
"Connection from ninja instances to Ninja constructor reestablished!");
for(let prop in Ninja.prototype){
assert(prop === "dance", "The only enumerable property is dance!");
}
使用Object.defineProperty()对原constructor设置不可枚举的constructor属性
instanceof
用于检测左边类与右边类是否是同一个子类,注意原型是否发生改变。
class -ES6
class提供了一种更为优雅的创建对象和实现继承的方式,但是其底层实现仍然是基于原型。
class Ninja{
constructor(name, level){
this.name = name;
this.level = level;
}
swingSword() {
return true;
}
static compare(ninja1, ninja2){//静态方法
return ninja1.level - ninja2.level;
}
}
class 如何实现继承?
class Person {
constructor(name){
this.name = name;
}
dance(){
return true;
}
}
class Ninja extends Person {
construct(name, weapon){
//super(name); //Uncomment this line of code when super gets supported.
this.weapon = weapon;
}
wieldWeapon(){
return true;
}
}
原型方法与实例方法区别
//one
function Person(firstName, secondName) {
this.firstName = firstName;
this.secondName = secondName;
this.getFullName = function () {
return this.firstName + "" + this.secondName;
}
}
//two
function Person(firstName, secondName) {
this.firstName = firstName;
this.secondName = secondName;
}
Person.prototype.getFullName = function () {
return this.firstName + "" + this.secondName;
}
第一种getFullName方法是在Person构造函数内创建的实例方法,凡是使用Person构造函数创建的对象都具有各自的getFullName方法;
第二种,定义在Person原型上,范式用Person构造函数创建的对象可以访问;