面向对象编程(二)

338 阅读2分钟

在上一篇文章知道如何使用object或对象字面量方便的创建对象,但是还是有所不足,这导致创建相同接口的多个对象需要重复定义,代码的复用率差,所以在ES6 正式支持类和继承。

工厂模式

function person(name,sex,year){
    let o=new Object();
    let o.name=name;
    let o.sex=sex;
    let o.year=year;
    let o.selfDescriptor=function(){
     console.log(this.name)   
    }
    return o;
}
let person1=person('yangyang','男',24);
console.log(person1);
//{
// name: 'yangyang',
// sex: '男',       
//year: 24,
// selfDescriptor: [Function (anonymous)]
//}

工厂模式虽然可以创建类似的对象,但是没有解决对象标识的问题

构造函数模式

function Person(name,sex,age){
this.name=name;
this.sex=sex;
this.age=age;
this.sayname=function(){
​
console.log(this.name);
}
}
​
let person1=new Person('fangfua','女'33);
let person1=new Person('lulu','男'21);
person1.sayname();//fangfua
person2.sayname();//lulu

与工厂模式的不同

  • 没有显示的创建对象
  • 属性和方法直接赋值给了this
  • 没有return
  • 函数名首字母需要大写

new操作符创建实例时内部发生了什么

  1. 在内存中创建了一个新对象

  2. 这个新对象的内部[[Prototype]]特性被赋值为构造函数的prototype属性

  3. 构造函数里面的this被赋值给这个新对象

  4. 执行构造函数的代码,给新对象添加属性

  5. 如果构造函数返回非空对象,则返回该对象,否则,返回刚创建的对象

    在构造实例化时如果没有传递参数,则构造函数后面的括号可以删除

原型模式

使用原型对象,它上面定义的属性和方法可以被实例共享;

function Person(){
Person.prototype.name="fangfua";
Person.prototype.sex='女';
Person.prototype.age=33;
Person.prototype.sayname=function(){
​
console.log(this.name);
}
}
​
let person1=new Person();
let person1=new Person();
person1.sayname();//fangfua
person2.sayname();//fangfua 

只要一创建一个函数,就会按照规则,为函数创建一个prototype属性指向原型对象,而原型对象也会有一个constructor的属性,指向与之关联的构造函数;

每次创建实例的时候,构造函数的[[prototype]]属性就会赋值给实例对象,就是proto

注意:实例和原型有直接的关联,而实例和构造函数则没有

如何判断实例对象和构造函数有同一个原型对象呢

原型.isPrototypeOf(实例)

例子:Person.prototype.isPrototypeOf(person1)//true

Object.getPrototypeOf()返回参数的内部的特性[[prototype]]的值

原型层级

function Person(){
Person.prototype.name="fangfua";
Person.prototype.sex='女';
Person.prototype.age=33;
Person.prototype.sayname=function(){
​
console.log(this.name);
}
}
​
let person1=new Person();
let person1=new Person();
​
person1.name='gungun';
console.log(person1.name);//gungun源自实例
console.log(person2.name);//fangfua源自原型
​
​

在实例对象上查找某个属性,会从实例本身查找,如果没有找到会从原型对象上找

Object.hasOwnProperty()方法可以判断属性是否出现在实例上还是原型上(true是实例上,false是原型上)

有三个方法可以遍历出实例或原型上的属性名称或者值

for...in

Object.keys()

function Person(){
Person.prototype.name="fangfua";
Person.prototype.sex='女';
Person.prototype.age=33;
Person.prototype.sayname=function(){
​
console.log(this.name);
}
}
​
let keys=Object.keys(Person.prototype);
console.log(keys)//name,sex,age.sayname

Object.values()

const o={
foo:'bar',
baz:1,
qux:{}
}
​
console.log(Object.values(o));//['bar',1,{}]