js 对象及实现一个new

370 阅读2分钟

对象

关于理解对象这个概念,我觉得这篇文章讲的好好 浅析面向过程与面向对象

其中介绍了什么是对象,面向过程和面向对象的区别是什么

如何创建对象

1.工厂模式
function createPerson(name,age,job){
	var o = new Object()
    o.name = name
    o.age = age
    o.job = job
}

var person = createPerson('joker','15','歌手')

缺点:无法知道创建出的对象的类型

2.构造函数

目前js有一些原生构造函数Object Array来创建对象,也可以自定义构造函数

function Person(name,age,job){
	this.name = name
    this.age = age
    this.job = job
    this.sayName = function(){
    	console.log(this.name)
	}
}

var person = new Person('joker','15','歌手')

使用new操作符创建对象,会经过以下几个步骤(高级程序设计)

  • 创建一个新对象
  • 将构造函数的作用域赋值给新对象(因此this指向了这个新对象)
  • 指向构造函数中的代码(给新对象添加属性)
  • 返回新对象
代码大概这样
// ES5构造函数
let Parent = function (name, age) {
    //1.创建一个新对象,赋予this,这一步是隐性的,
    // let this = {};
    //2.给this指向的对象赋予构造属性
    this.name = name;
    this.age = age;
    //3.如果没有手动返回对象,则默认返回this指向的这个对象,也是隐性的
    // return this;
};
const child = new Parent();

winter 的描述

  • 以构造器的 prototype 属性(注意与私有字段[[prototype]]的区分)为原型,创建新对象;
  • 将 this 和调用参数传给构造器,执行;
  • 如果构造器返回的是对象,则返回,否则返回第一步创建的对象。
代码大概这样
// 构造器函数
let Parent = function (name, age) {
    this.name = name;
    this.age = age;
};
Parent.prototype.sayName = function () {
    console.log(this.name);
};
//自己定义的new方法
let newMethod = function (Parent, ...rest) {
    // 1.以构造器的prototype属性为原型,创建新对象;
    let child = Object.create(Parent.prototype);
    // 2.将this和调用参数传给构造器执行
    let result = Parent.apply(child, rest);
    // 3.如果构造器没有手动返回对象,则返回第一步的对象
    return typeof result  === 'object' ? result : child;
};
//创建实例,将构造函数Parent与形参作为参数传入
const child = newMethod(Parent, 'echo', 26);
child.sayName() //'echo';

//最后检验,与使用new的效果相同
child instanceof Parent//true
child.hasOwnProperty('name')//true
child.hasOwnProperty('age')//true
child.hasOwnProperty('sayName')//false

Object.create(person) 方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。 简而言之,就是传入的person是创建出来对象的__proto__属性

缺点:每次使用构造函数,构造函数里的方法会重新创建,占用内存空间

解决方法

function Person(name,age,job){
	this.name = name
    this.age = age
    this.job = job
    this.sayName = sayName
}

function sayName(){
    console.log(this.name)
}

var person = new Person('joker','15','歌手')

缺点:暴露了全局方法,后期不易维护

3.原型模式
function Person(){}
Person.prototype.name = '薛之谦'
var person1 = new Person()
console.log(person1.name) // 薛之谦

优化

function Person() {}

Person.prototype = {
    constructor: Person,
    name: '薛之谦',
    getName: function () {
        console.log(this.name);
    }
};

var person1 = new Person();
console.log(person1.name) // 薛之谦

缺点:所有的属性和方法共享

4.组合模式
function Person(name) {
    this.name = name;
}

Person.prototype = {
    constructor: Person,
    getName: function () {
        console.log(this.name);
    }
};

var person1 = new Person();
还有几种 以后用到再补充吧