[写作中...]Js面向对象(2): 创建对象

260 阅读4分钟

目标

  • 理解对象
  • 创建对象实例
  • 理解Js中的继承

前言

理解对象中了解到了两种最简单的创建对象的方式,本篇详细讨论Js中各种创建对象的方法。

创建对象

重点需要搞清楚构造函数模式原型模式组合使用两种模式的创建对象实例方法。(明白前两个其实大概就明白了如何组合使用)

1、工厂模式

工厂模式是一种广泛使用的设计模式, 创建对象的工厂模式,简单地理解就是new Object()创建对象的具体过程封装为一个函数

function CreatSomething(){
    const o = new object();
    o.propertyName1='value1';
    o.propertyName2='value2';
    ...
    o.functionName=function (){
        console.log(this.propertyName1);
    }
}

工厂模式存在的问题是,没有解决对象识别的问题(无法判断一个对象是由哪个函数实例化的),因此用的也不多,作为一个了解。

2、构造函数模式

2.1、普通构造函数模式

通过Js的一些内置对象可以创建对象实例,如ObjectArray等,也可以自定义构造函数,如:

funtion Something(val,num){
    this.propertyName1=val;
    this.propertyName2=num;
    ...
    this.functionName=function (){
        console.log(this.propertyName1);
    }
}
const something1=new Something('val1',21);
const something2=new Something('val2',20);

与工厂模式的区别在于:

  • 可以不用显式地创建对象(原因是被new承包了) ...=new Object()
  • 属性方法赋给了this对象
  • 可以不return新对象

所以相比工厂模式,使用构造函数创建对象实例更简洁,高效。

那么,构造函数是如何将属性和方法赋给实例对象的呢?
关键在于:

2.2、new操作符

对于new操作符,我觉得理解下其执行步骤,应该就清楚了

  • (1) 创建一个新对象
  • (2) 将构造函数的作用域赋给新对象(将this绑定到这个新创建的对象)
  • (3) 执行构造函数中的代码(将属性和方法添加到这个新对象)
  • (4) 返回该对象

补充:模拟一个new操作符的实现(建议了解清楚原型之后再回过头来看)

function myNew(func){
    const objNull={};  //新对象
    if (func.prototype !== null){
        obj.__proto__=func.prototype; 
    }
    const obj=func.apply(res,Array.prototype.slice.call(arguments,1));  //绑定this
    if ((typeof obj === "object" || typeof obj === "function") && obj !==null){
        return obj;
    }
    return objNull;
    
}

在StackOverflow查阅new的时候看到一个评论戳中笑点...

2.3、思考:构造函数创建对象实例存在的问题?

简单来说,构造函数的问题在其对象的方法上。

3、原型模式

3.1、理解原型对象

我们创建的每一个函数都有一个prototype指针,指向一个对象(即原型对象),包含由当前函数派生出的所有实例共享的属性和方法

当调用构造函数创建实例后,实例内部将会包含一个[[prototype]]指针(浏览器中的实现是__proto__),指向其构造函数的原型对象prototype

所以简单总结下,

  • 实例.__proto__=构造函数.prototype
  • 另外ES5中封装了一个方法,MDN建议使用这种方式来操作
    • Object.getPrototypeOf(实例)==构造函数.prototype
function Person(){...}
const someone=new Person();

someone.__proto__===Person.prototype                            //true
Object.getPrototypeOf(someone)===Person.prototype               //true

3.2、普通原型模式

function Person(){
    
}
Person.prototype.property1=val1;
Person.prototype.property2=val2;
Person.prototype.funcName=function (){
    console.log(this.property1)
};

const someone = new Person();
someone.fucName()  // 输出val1

3.3、内置对象的原型


Object Array Date RegExp FUnction 

基本包装类型
Boolean Number String

单体内置对象
Global Math

3.4、思考:原型模式创建对象实例存在的问题?

对象中值为引用类型的属性会被各实例共享,也就是说在原型模式下,改变一个实例对象的 引用类型属性值会影响到其他所有实例对象。

4、组合使用构造韩式和原型模式

更多创建对象实例的方式

动态原型模式

寄生构造函数模式

稳妥构造函数模式

小结

此处应该有个小结,不过还没想好该写些什么。

水平有限,不准确的地方,欢迎指正。

参考: