面向对象的程序设计——创建对象

1.普通对象声明

创建自定义对象的最简单方式就是创建一个Object的实例,然后在为他们添加属性和方法,如下所示:

var person = new Object();        //创建对象
person.name = "Nicholas";        //添加属性
person.age = 29;
person.job = "teacher";
person.sayName = function(){    //添加方法
    alert(this.name);
};

this的含义:

  1. this表示当前作用域下的对象;
  2. this表示new Objecy()实例化出来的那个对象;
  3. this要放在一个作用域下,比如person.sayName()person下的方法,方法可用this表示方法本身。

缺点:要创建一个类似的对象会产生大量的代码。

为了解决多个类似声明的问题,用一种工厂模式,这种方法是为了解决实例化对象产生大量重复的代码。

2.工厂模式

用函数来封装以特定接口创建对象的细节。

function createPerson(name,age,job){    //创建对象
    var obj = new Object();                //添加属性
    obj.name = name;
    obj.age = age;
    obj.job = job;
    obj.sayName = function(){            //添加方法
        alert(this.name);
    };
    return obj;                            //返回对象引用
}

var person1 = createPerson("Zhangsan",29,"Teacher");    //实例化第一个对象
var person2 = createPerson("Lisi",34,"Doctor");        //实例化第二个对象
alert(person2 instanceof Object)        //true

this的含义: 1.thisnew Object,实例化出来的那个对象; 2.this要放在一个作用域下,比如obj.sayName(){},这是o作用域下的的方法,可以用this来表示obj本身。

缺点:虽然集中实例化函数,解决了大量重复的代码,但不管怎样他们都是Object类型,就无法区分谁是谁的对象。

3.构造函数模式

构造函数可用来创建特定类型的对象,类似Object类型。

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

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

var person1 = new Person("Zhangsan",29,"Teacher");
var person2 = new Person("Lisi",34,"Doctor");    
var person3 = new Person2("Wangwu",34,"Police");

alert(person1 instanceof Person);        //true,person1从属于Person
alert(person2 instanceof Person);        //true,person2从属于Person
alert(person3 instanceof Person2);        //true,person3从属于Person2
alert(person1 instanceof Person2);        //false,因为这里person1是从属于Person

alert(person1.sayName() == person2.sayName());    //true,构造函数的方法的值是想等的
alert(person1.sayName == person2.sayName);    //false,比较的是引用地址

构造函数和工厂模式的区别:

  1. 构造函数没有new Object但它后台会自动生成var obj = new Object();
  2. this相当于obj
  3. 构造函数没有return语句,他是后台自动返回的。

构造函数规则:

  1. 构造函数也是函数,但函数名第一个字母大写;
  2. 必须new 构造函数名(),如new Person(),而Person第一个字母也是大写的。

构造函数解决识别问题: 要在创建出来一个构造函数,并实例化之后才能比较出来。

构造函数与普通函数的区别: 调用方式不同,构造函数使用new调用,普通函数则无需。

构造函数虽然可以当做普通函数调用,但因为构造函数是要被封装起来的,内部是不允许修改的,它内部是没有return语句的,所以构造函数,用普通函数调用是无效的,必须使用new运算符。

缺点:每个方法都要在实例上重新创建一遍。

4.把方法移动到构造函数外部

这做法没什么必要,只是加深学习了解:

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

function sayName(){            //把构造函数内部的方法通过全局来实现,引用地址一致
    alert(this.name);
}

var person1 = new Person("Zhangsan",29,"Teacher");
var person2 = new Person("Lisi",34,"Doctor");    

alert(this.name)this含义 这个this当作对象调用的话,this代表Person,当普通函数调用this代表window

函数(方法)如果没有圆括号,输出函数代码,有括号才会输出函数值。

缺点:在全局作用域中定义的函数只能被某个对象调用,让全局作用域有点名不副实。

5.原型模式

使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。

  1. 如果是实例方法,不同的实例化,不同的实例化,它们的方法和地址是不一样的,是唯一的;
  2. 如果是原型方法,那它们的地址是共享的,大家都一样。
function Person(){}        //构造函数什么体内什么都没有,如果有叫做实例方法,实力属性

Person.prototype.name = "Zhangsan";
Person.prototype.age = 29;
Person.prototype.job = "Teacher";
Person.prototype.sayName = function(){
    alert(this.name);
};

var person1 = new Person();
person.sayName = "Zhangsan";

var person2 = new Person();
person.sayName = "zhangsan";

alert(person1.sayName == person2.sayName);    //true

缺点:重复敲Person.prototype,造成大量的重复输入。

6.字面量方式创建原型

function Person(){}//使用字面量的方式创建原型对象,这里的`{}`就是对象,是`Object`,`new Object`相当于`{}`

Person.prototype = {
    name: "Zhangsan",
    age: 29,
    job: "Teacher",
    sayName: function(){
        alert(this.name);
    }
};

var person = new Person();

注意:实例化后重写原型对象,会切断现有实例和新原型之间的联系 缺点:constructor不在指向实例,而会指向Object。新对象的constructor重写Person原来的constructor,因此会指向新对象。 解决方法:在原型内部,可以设置constructor强行执行实例。

7.组合构造函数模式和原型模式

构造函数模式用于定义实力属性,原型模式用于定义方法和共享属性

function Person(name,age,job){        //保持独立的使用构造函数
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Xiaoming","Fangfang"];
}

Person.prototype = {        //保存共享的使用原型
    constructor: Person,
    sayName: function(){
        alert(this.name);
    }
}

var person1 = new Person("Zhangsan",29,"Teacher");
var person2 = new Person("Wangwu",34,"Doctor");

person1.friends.push("Xiaohong");
alert(person1.friends);    //"Xiaoming,Fangfang,Xiaohong"
alert(person2.friends);    //"Xiaoming,Fangfang",引用类型没有使用原型,所以没有共享
alert(person1.friends == person2.friends);    //false
alert(person1.sayName == person2.sayName);    //true

8.动态原型模式

动态原型模式,把所有信息都封装在了构造函数中。

function Person(name,age,job){        //保持独立的使用构造函数
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Xiaoming","Fangfang"];

    if(typeof this.sayName != "function"){    //仅在第一次时初始化
        Person.prototype.sayName = function(){
            alert(this.name);
        };
    }
}

原型的初始化,只要第1次初始化,就可以了,没必要每次构造函数实例化的时候都初始化,可以将原型封装在函数里。 注意:使用动态原型模式时,不能使用对象字面量重写原型。如果在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系。

原文链接:segmentfault.com

上一篇:简单理解 JavaScript Event Loop
下一篇:get a total of jquery's .each()

相关推荐

  • 高程读书笔记 第六章 面向对象程序设计

    本章内容 ECMA-262把对象定义为:无序属性的集合,其属性可以包含基本值、对象或者函数 理解对象 创建对象 创建自定义对象的最简单方式就是创建一个Object的实例,再为它添加属性和方法。

    2 年前
  • 面向对象编程(三)

    Object对象中相关方法的介绍 Object对象本身的方法 Object的静态方法 Object.keys() 获取键,参数是一个对象,返回是一个数组。Object.keys()只能获取可枚举的属性...

    1 个月前
  • 面向对象的程序设计——理解对象

    面向对象的程序设计 ECMA-262 把对象定义为:无须属性的集合,其属性可以包含基本值、对象或者函数。 理解对象 var person = new Object(); //创建对象 p...

    3 年前
  • 面向对象的小九九

    本人能力有限,有误请斧正 本文旨在复习面向对象(不包含es6) 本文学习思维 创建对象的方式,获取对象属性 构造函数,构造函数的new 做了什么 原型与原型对象 原型链 继承(借用构造继承、原型继承...

    2 年前
  • 面向对象的封装、继承、多态以及构造函数

    1、面向对象特点:封装、继承、多态。 2、构造函数 = 构造器 + 原型对象; (1)父类 function UserClass(name,age,word){ //构造器 constructor t...

    1 年前
  • 面向对象的JavaScript构造函数模式:新古典与原型

    Cheeso提出了一个问题:OO Javascript constructor pattern: neo-classical vs prototypal,或许与您遇到的问题类似。

    3 年前
  • 面向对象的JavaScript最佳实践?[关闭]

    gnovicee-satis提出了一个问题:Object Oriented Javascript best practices? [closed],或许与您遇到的问题类似。

    3 年前
  • 面向对象和面向过程分别是什么?

    世界上有loli控,御姐控,女王控,所以有句话就叫万物皆可控 面向对象也是一样,万物皆对象 对象这个词你可以理解为一个总称,比如男人女人都叫人,蜡烛皮鞭高跟鞋都是道具,所以面向对象原本的意思是“都叫对...

    5 个月前
  • 面向对象关键知识点汇总

    先来了解一些基础概念,才能更好的理解知识。 对象的定义 ECMA-262把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数。 数据属性 4个特性 以上属性一般通过Object.de...

    2 年前
  • 面向对象不是银弹,DDD 也不是,TypeScript 才是

    要解决的问题是什么? A problem well-stated is Half-solved Fred Brooks 在著名的"No Silver Bullet - Essence and Acci...

    1 年前

官方社区

扫码加入 JavaScript 社区