js基础-八种建立对象方法

建立对象方法

  1. Object构造函数
  2. 对象字面量表示
  3. 工厂模式
  4. 构造函数模式
  5. 原型模式
  6. 构造函数模式与原型模式结合
  7. 动态原型模式
  8. 寄生构造函数模式

1、Object实例建立

var person1 = new Object();
person1.name = "bob";
person1.age = '22';
person1.job = 'frontend';

person1.sayName = function () {
    console.log(this.name);
}

person1.sayName(); // bob
console.log(person1.age); // 22

2、对象字面量表示

var person2 = {
    name: 'bob',
    age: 22,
    job: 'frontend',
    sayName: function () {
        console.log(this.name);
    }
}
person2.sayName(); // bob

3、工厂模式

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;
}

var person1 = createPerson('bob', 22, 'frontend');
var person2 = createPerson('lynn', 22, 'doctor');

console.log(person1.name); // bob
console.log(person2.name); // lynn
  • 优势:函数封装建立对象,无需写重复建立对象的代码
  • 缺点:没有解决对象识别的问题(怎么样知道一个对象类型)

4、构造函数模式

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function () {
        console.log(this.name);
    }
    
    /**
     * 与声明函数在逻辑上是等价的
       this.sayName = new Function("console.log(this.name)"); 
    */
}

var person1 = new Person('bob', 22, 'frontend');
var person2 = new Person('lynn', 22, 'doctor');

console.log(person1.name); // bob
console.log(person2.name); // lynn
优势:
  • 没有显式地建立对象
  • 直接将属性和方法赋给了this对象
  • 没有return语句
缺点:
  • 每一个方法都要在每一个实例上从新建立一遍
实现过程:
  • 建立新的对象
  • 将构造函数的做用域赋给新对象,所以this就指向了这个对象
  • 执行构造函数的代码,为这个对象添加对象属性和方法
  • 返回新的对象

person1person2分别保存着Person的一个不一样的实例。这两个对象都有一个constructor(构造函数)属性,该属性指向Personfrontend

console.log(person1.constructor === Person); // true
console.log(person2.constructor === Person); // true

对象的constructor属性最初是用来标识对象类型的。可是,提到检测对象类型,仍是instanceof操做符要更可靠一些函数

console.log(person1 instanceof Object); // true
console.log(person1 instanceof Person); // true
console.log(person2 instanceof Object); // true
console.log(person2 instanceof Person); // true

咱们在这个例子中建立的全部对象既是Object的实例,同时也是Person的实例,这一点经过instanceof操做符能够获得验证,建立自定义的构造函数意味着未来能够将它的实例标识为一种特定的类型优化

能够将构造函数看成函数
// 看成构造函数使用
var person = new Person("bob", 22, "frontend");
person.sayName(); //"Nicholas"

// 做为普通函数调用
Person("lynn", 22, "doctor"); // 添加到window
window.sayName(); //"Greg"

// 在另外一个对象的做用域中调用
var o = new Object();
Person.call(o, "Kristen", 25, "Nurse");
o.sayName(); //"Kristen"
缺点优化

构造函数建立的对象方法,实际上执行屡次函数建立,会致使不一样的做用域链和标识符解析,如:this

console.log(person1.sayName == person2.sayName);  //false

建立两个完成一样任务的Function实例的确没有必要;何况有this对象在,根本不用在执行代码前就把函数绑定到特定对象上面。所以,大可像下面这样,经过把函数定义转移到构造函数外部来解决这个问题。prototype

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

// 把sayName函数抽离出外部函数
function sayName() {
    console.log(this.name);
}

存在问题:指针

  • 全部被新建立出来的对象,都会指向全局做用域的sayName函数,若是定义N个方法,那么就要定义N个全局的方法,这就形成了封装性的瓶颈,不过可使用原型模式来解决

5、原型模式

function Person() {
}

Person.prototype.name = 'bob';
Person.prototype.age = 22;
Person.prototype.job = 'frontend';
Person.prototype.sayName = function () {
    return this.name
}

var person1 = new Person();

console.log(person1.name); // bob
console.log(person1.age); // 22
console.log(person1.job); // frontend
console.log(person1.sayName()); // bob
console.log(person1.sayName === person2.sayName); // true

咱们建立的每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含能够由特定类型的全部实例共享的属性和方法。若是按照字面意思来理解,那么prototype就是经过调用构造函数而建立的那个对象实例的原型对象。使用原型对象的好处是可让全部对象实例共享它所包含的属性和方法。code

6、组合使用构造函数模式和原型模式

function Person(name, age, obj) {
    this.name = name;
    this.age = age;
    this.obj = obj;
}

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

var person1 = new Person('bob', 22, 'frontend');
var person2 = new Person('lynn', 22, 'doctor');

console.log(person1.name); // bob
console.log(person2.name); // lynn
console.log(person1.sayName === person2.sayName); // true

7、动态原型模式

function Person(name, age, obj) {
    this.name = name;
    this.age = age;
    this.obj = obj;

    console.log('typeof this.sayName: ', typeof this.sayName);
    // 检测sayName 是否是一个函数
    // 实际上只在当前第一次时候没有建立的时候在原型上添加sayName方法
    if (typeof this.sayName != 'function') {
        Person.prototype.sayName = function () {
            return this.name;
        }
    }
}

var person1 = new Person('bob', 22, 'frontend');
var person2 = new Person('lynn', 22, 'doctor');

console.log(person1.name); // bob
console.log(person2.name); // lynn
console.log(person1.sayName()); // bob
console.log(person2.sayName()); // lynn
console.log(person1.sayName === person2.sayName); // true

8、寄生构造函数模式

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;
}

var person1 = new createPerson('bob', 22, 'frontend');
var person2 = new createPerson('lynn', 22, 'doctor');

console.log(person1.name); // bob
console.log(person2.name); // lynn
相关文章
相关标签/搜索