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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,928评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,748评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,282评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,065评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,101评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,855评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,521评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,414评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,931评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,053评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,191评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,873评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,529评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,074评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,188评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,491评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,173评论 2 357

推荐阅读更多精彩内容