ES5没有正式支持面向对象,而是利用原型式进行继承。ES6引入类,是对ES5的类和原型继承进行封装的语法糖。
是指一个接收固定参数的函数,用new Object()的形式,用参数创建对象及其属性和方法。
function create(name,age,job){
let o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
console.log(this.name);
};
return o;
}
let person1 = create("alex",20,"SE");
能够创建多个类似的对象,但是没办法确定对象的类型,它只是Object类型。
原生构造函数:Object Array,通过自定义构造函数,为自己的对象类型定义属性和方法。
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
console.log(this.name);
};
return o;
}
let person1 = new Person("alex",20,"SE"); //传统调用方法,新建Person对象
let o = new Object();
Person.call(o,"alex",20,"SE"); //在另一个对象的作用域中调用,以o作为构造函数的this值,属性和方法添加到对象o中
console.log(person1 instanceof Person) //true
console.log(person1 instanceof Object) //true
console.log(person1.constructor == Person) //true
构造函数定义的方法会在每个实例上都创建一遍。所以每个实例的同一个函数都不是一个实例。
解决构造函数模式创建函数实例的缺点,利用函数的prototype(原型),共享属性和方法。
function Person(){}
Person.prototype.name = "Nicholas";
Person.prototype.age = 20;
Person.prototype.job = "SE";
Person.prototype.sayName = function(){console.log(this.name);};
let person1 = new Person(); //新建Person对象
person1.sayName(); //"Nicholas"
因此如果想覆盖原型的属性,那么就在实例中添加一个同名的属性。
若在实例中或者原型中添加了同名的属性,但是想删除了,那么需要用到delete
操作符
delete person1.name;
可以用hasOwnProperty()
方法看属性是否是实例本身的,是则返回true
person1.hasOwnProperty("name"); //true or false
in操作符会在可以通过该对象访问指定属性的时候,返回true,无论是通过对象实例还是对象原型。
console.log("name" in person1) //ture
所以,如果hasOwnProperty返回false in操作符返回true,属性就是在原型上。
当实例1的原型是原型2的实例,那么就会构成一个 实例1-->原型1(实例2)-->原型2的一个原型链。
介绍原型链有助于理解继承过程,后面会直接介绍继承的方法
如图所示:
继承了父类之后,经常要新增方法或者覆盖父类的方法,那就要等原型赋值之后,在对原型新增方法或者覆盖方法。
function SuperType(){
this.property=true;
};
SuperType.prototype.getSuperValue = function(){
return this.property;
}
function SubType(){
this.subProperty = false;
}
SubType.prototype = new SuperType();
//新方法
SubType.prototype.getSubValue = function(){
return this.subproperty;
}
//修改旧方法
SubType.prototype.getSuperValue = function(){
return false;
}
注:以对象字面量方式创建原型的方法的时候,相当于重写原型,破坏原来的原型链。
SubType.prototype = new SuperType();
//这样添加新方法,导致原型被重写,上一句无效
SubType.prototype = {
getSubValue(){
return this.subProperty;
}
get SuperValue(){
return this.superProperty;
}
}
原型包含引用值时,不能够实现每个实例封装的特性。所以一般属性值会写在构造函数中,方法写在原型内。
1 但是在原型链中,父原型的实例变成了子实例的原型,属性放在构造函数里也会出现问题了。
2 子类型在实例化的时候,不能给父类型的构造函数传递参数。
所以原型链不会单独进行使用
原文:https://www.cnblogs.com/zhangjw83/p/14826625.html