JavaScript 创建对象(工厂模式,构造函数模式,原型模式)

工厂模式

function createPerson(name ,age ,job){
   var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
        console.log(this.name);
    }
    return o;
}
  • 虽然解决了创建多个相似对象的问题,但是没有解决对象识别的问题(即怎样知道一个对象的类型)。

构造函数模式

function Person(name, age ,job){
    this.name = name ;
    this.age = age;
    this.job = job;
    this.sayName = function(){
        console.log(this.name);
    }
}
var person1 = new Person("kaifa",21,"Boss");
console.log(person1 instanceof Person); //true
console.log(person1 instanceof Object); //true
  • 按照惯例,构造函数始终都应该以一个大写字母开头。
  • 可以使用instanceof检测对象类型。
  • 多种使用方式
//当做普通函数调用
Person("FAFA",22,"Manager");
window.sayName();

//在另一个对象的作用域中调用
var o = new Object();
Person.call(o ,"HAO",23,"Chairman");
o.sayName();
  • 使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一遍。可以把函数定义转移到构造函数外部,但是这样自定义的引用类型就丝毫没有封装性可言了。这种方式创建的函数,会导致不同的作用域链和标识符解析。
function Person(name, age ,job){
    this.name = name ;
    this.age = age;
    this.job = job;
    //在逻辑上与声明函数是等价的
    this.sayName = new Function("console.log(this.name)");
}
var person1 = new Person("kaifa",21,"Boss");
var person2 = new Person("kaifa",21,"Boss");
console.log(person1.sayName == person2.sayName);//false

原型模式

function Person(){
}

Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
    console.log(this.name);
}

var person1 = new Person();
var person2 = new Person();

个对象之间的关系:
这里写图片描述

  • 只要创建一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。在默认情况下所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针。Person.prototype.constructor指向Person。

  • 当用构造函数创建一个新实例后,该实例内部的将包含一个指针[[Prototype]],指向构造函数的原型对象。虽然在脚本中没有标准的方法来访问[[Prototype]],但Firefox,Safari,Chrome在每个对象上都支持一个属性_proto_。

  • 判断对象之间的关系
Person.prototype.isPrototypeOf(person1);//true

Object.getPrototypeOf(person1) == Person.prototype;//true

person1.__proto__ == Person.prototype;//true
  • 原型的动态性:每当代码读取某个对象的某个属性时,都会执行一次搜索,搜索首先从对象实例本身开始,如果实例中找到了具有给定名字的属性,则返回,否则继续搜索原型指针指向的原型对象。当修改了原型中的值,所有的实例对象都受到影响。
var person1 = new Person();
person1.name = "kaifa";
console.log(person1.name);
delete person1.name;
console.log(person1.name);
  • 原型对象的问题:当原型中包含引用类型时,如果我们的初衷就是共享一个数组,那没问题,可实例一般来讲都是要有属于自己的所有属性。
function Person() {
}
Person.prototype = {
    constructor: Person,
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    friends: ["Shelby", "Court"],
    sayName: function () {
        console.log(this.name);
    }
}

var person1 = new Person();
var person2 = new Person();
person1.friends.push("fafa");
console.log(person1.friends);//["Shelby", "Court","fafa"]
console.log(person2.friends);//["Shelby", "Court","fafa"]
  • 判断属性存在于实例中,还是存在于原型中
    hasOwnProperty():判断该对象中是否含有属性。
    in:判断是否能够访问。
person1.hasOwnProperty("name");//false
person1.name = "fafa";
person1.hasOwnProperty("name");//true
"name" in person1;//true
delete person1.name;
"name" in person1;//true
delete person1._proto_.name;
"name" in person1;//false

构造函数和原型组合使用

function Person(name ,age ,job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Shelby", "Court"];

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

猜你喜欢

转载自blog.csdn.net/weixin_42950052/article/details/81667144