【js基础】创建对象&函数的六种模式

*为更加清晰的了解原生JavaScript中的创建对象&函数,本文均采用ES5的语法。 

一、最简单的创建对象

1.使用new关键字创建Object

var student = new Object;

student.id = 12345;

student.name = "xiaoming";

student.sex = "male";

student.word = function() {

    alert("I am Xiaoming!")

}

2.对象字面量

var student = {

    id: 12345,

    name: "xiaoming",

    sex: "male",

    word: function() {

        alert("I am Xiaoming!")

    }

}

上面的两种方式,会产生大量的代码,而且没有复用性。由此,我们可以考虑采用工厂模式,即类似于工厂用一条流水线,批量生产的方式创建对象:

二、工厂模式

function createStudent(name,sex,id) {

    var o = new Object();

    o.name = name;

    o.sex = sex;

    o.id = id;

    o.word = function(){

        alert(this.name);

    }

    return o;

}

上面定义的函数createStudent,就是使用工厂模式的方式创建对象的。每次调用函数时,新建一个对象并给其属性赋值。

var student1 = createStudent("xiaoming", "male", 12345);

var student2 = createStudent("xiaoling", "female", 54321)

和直接创建对象相比,工厂模式大大节省了代码量,并且可复用,解决了重复实例化多个对象的问题。但同时也有一定的弊端:没有解决对象识别的问题。在JavaScript中,对象还包括Date、Array等特殊对象,仅通过工厂模式无法解决对象类型的识别。由此,我们可以采用构造函数:

三、构造函数模式

function Student(name,sex,hobby)  {

    this.name = name;

    this.sex = sex;

    this.hobby = hobby;

    this.word = function(){

        alert(this.name);

    }

}

以此方法调用构造函数步骤 {

1、创建一个新对象

2、将构造函数的作用域赋给新对象(将this指向这个新对象)

3、执行构造函数代码(为这个新对象添加属性)

4、返回新对象

}

//调用并生成对象

var student1 = new Student ("xiaoming", "male", ["singing", "soccer", "game"]);

var student2 = new Student ("xiaoling", "female", ["comic", "dancing", "reading"]);

console.log(student1 instanceof Object);  //true

console.log(student1 instanceof Student);  //true

console.log(student2 instanceof Object);  //true

console.log(student2 instanceof  Student );  //true

console.log(student1.constructor);   //constructor 属性返回对创建此对象的数组、函数的引用

instanceof运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置。由上例可以看出,通过构造函数创建的student1、student2既是Student的实例,也是Object的实例。这说明通过构造函数创建的对象是可以判断其对象类型的。

构造函数对比工厂模式有以下不同之处:

1、没有显式地创建对象

2、直接将属性和方法赋给了 this 对象

3、没有 return 语句

构造函数依然存在一些问题。虽然不再重复的显式创建对象,但是每次new一个Student时,其实也是每次都创建了一个Function。而Function也是对象的一种类型。其本质是多次创建了函数。为解决这个问题,产生了原型模式。

四、原型模式

function Student() {

}

Student.prototype.name = "xiaoming";

Student.prototype.sex = "male";

Student.prototype.hobby= ["singing", "soccer", "game"];

Student.prototype.word = function(){

    alert(this.name);

};

由上面代码可以看出,Student的属性定义在了它的原型(prototype)上。这样的方式可以使得Student所有对象实例共享它的属性和方法,无需在每次创建对象时都要创建一份新的属性和方法,直接定义属性和方法在对象的原型上,可以使得所有实例都直接继承。

console.log(Student.prototype);  //Object{name: 'xiaoming', sex: "male", hobby: Array[3]}

var student1 = new Person();        //创建一个实例person1

console.log(student1.name);        //xiaoming

student1.name = "xiaojun";

console.log(student1.name);        // xiaojun

上文可以看出,在实例上再次定义同名的属性(私有属性),可以覆盖其原型上的公有属性。

五、组合模式(构造函数模式+原型模式)

单纯的构造函数和原型模式各有优缺点。因此,我们可以利用构造函数模式定义实例属性,原型模式用于定义方法和共享的属性,结合两者的优点使用。

//构造函数定义属性:

function Student(name,sex,hobby){

    this.name = name;

    this.sex= sex;

    this.hobby= hobby;

}

//原型定义方法:

Student.prototype = {

    constructor: Student,  //让构造器指向自身

    word: function(){

        alert(this.name);

    }

}

var student1 = new Student("xiaoming","male",["singing", "soccer", "game"]);

console.log(student1);

上面代码中的constructor的意思是,每个函数都有prototype属性,指向该函数原型对象,原型对象都有constructor属性,是一个指向prototype属性所在函数的指针。具体对面向对象的constructor的解读,可看文章连接:https://www.jianshu.com/p/49e5e848fee0

在其他面向对象的语言中,属性和方法往往是封装在一起的,而在组合模式中,构造函数和原型是分开定义了属性和方法的,所以并没有真正意义上的封装,因此,动态原型模式正是解决这一问题的方案。

六、动态原型模式

动态原型模式是将属性和方法都封装在构造函数中(包括原型属性和实例属性),通过在构造函数中实例化原型(仅在必要的情况下)实现封装,又保持了同时使用构造函数和原型的优点。其本质是在构造函数中加了一层对于方法的判断,从而实现动态生成原型上的方法。

function Student(name,sex,hobby){

        this.name = name;

        this.sex = sex;

        this.hobby = hobby;

        if(typeof this.word != "function") {//这段判断语句的作用是限制Person.prototype属性(原型属性对象)只生成一次,要不然每次实例化一个Person对象都会去写一遍原型对象

            Student.prototype.word = function () {

                alert(this.name);

            }

        }

    }

    var student1 = new Student("xiaoming","male",["singing", "soccer", "game"]);

创建Student构造函数时,会创建一个prototype属性,该属性实际上就是Student.prototype的原型对象,prototype属性是一个指针,指向Person.prototype的原型对象,

当this指向的属性非方法(typeof this.word != "function"),则在当前对象的原型上创建一个新方法。避免了重复修改原型方法。

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

推荐阅读更多精彩内容

  • 一、面向过程和面向对象的区别、联系 1.面向过程编程:注重解决问题的步骤,分析问题需要的每一步,实现函数依次调用。...
    空谷悠阅读 898评论 1 11
  • avaScript对每个创建的对象都会设置一个原型,指向它的原型对象。 当我们用obj.xxx访问一个对象的属性时...
    源大侠阅读 251评论 0 1
  • 博客内容:什么是面向对象为什么要面向对象面向对象编程的特性和原则理解对象属性创建对象继承 什么是面向对象 面向对象...
    _Dot912阅读 1,415评论 3 12
  • 上海,又发生了一起惨剧: 一大学生养狗起纠纷活活打死邻居。 8月23日深夜,上海青浦某小区一女孩儿取快递,快递柜跟...
    屠龙奶爸阅读 876评论 0 2
  • 20分钟刷了一只毒液,这种画法很不精致,但很解压。 日常记录自己的绘画,突然发现点赞的人很少,且评论的人很苛刻。 ...
    小陀弥阅读 477评论 0 9