Jadual Kandungan
最简单的方式
对象字面量形式
使用Object构造函数
工厂模式
构造函数模式
原型模式
组合使用构造函数模式和原型模式
动态原型模式
寄生构造函数模式
稳妥构造函数模式
结语
Rumah hujung hadapan web tutorial js JS对象创建常用方式有哪些?

JS对象创建常用方式有哪些?

Jun 28, 2017 am 09:55 AM
javascript prinsip Cara

前言

俗话说“在js语言中,一切都对象”,而且创建对象的方式也有很多种,所以今天我们做一下梳理

最简单的方式

JavaScript创建对象最简单的方式是:对象字面量形式或使用Object构造函数

对象字面量形式

1 var person = new Object();2   person.name = "jack";3   person.sayName = function () {4   alert(this.name)5 }
Salin selepas log masuk

使用Object构造函数

1 var person = {2   name: "jack";3   sayName: function () {4     alert(this.name)5   }6 }
Salin selepas log masuk

明显缺点:创建多个对象时,会出现代码重复,于是乎,‘工厂模式’应运而生

工厂模式

通俗一点来理解工厂模式,工厂:“我创建一个对象,创建的过程全由我来负责,但任务完成后,就没我什么事儿了啊O(∩_∩)O哈哈~”

 1 function createPerson (name) { 2   var o = new Object(); 3   o.name = name; 4   o.sayName = function () { 5     alert(this.name) 6   } 7   return o 8 } 9 10 var p1 = new createPerson("jack");
Salin selepas log masuk

明显缺点:所有的对象实例都是`Object`类型,几乎类型区分可言啊!你说无法区分类型,就无法区分啊,我偏不信!那咱们就来看代码吧:

1 var p1 = new createPerson("jack");2 var p2 = new createPerson("lucy");3 4 console.log(p1 instanceof Object); //true5 console.log(p2 instanceof Object); //true
Salin selepas log masuk

你看,是不是这个理儿;所以为了解决这个问题,我们采用‘构造函数模式’

构造函数模式

构造函数模式,就是这个函数我只管创建某个类型的对象实例,其他的我一概不管(注意到没有,这里已经有点类型的概念了,感觉就像是在搞小团体嘛)

 1 function Person (name) { 2   this.name = name; 3   this.sayName = function () { 4     alert(this.name) 5   } 6 } 7  8 function Animal (name) { 9   this.name = name;10   this.sayName = function () {11     alert(this.name)12   }13 }14 15 var p1 = new Person("jack")16 p1.sayName() //"jack"17 18 var a1 = new Animal("doudou")19 a1.sayName() //"doudou"20 21 console.log(p1 instanceof Person) //true22 console.log(a1 instanceof Animal) //true23 console.log(p1 instanceof Animal) //false(p1显然不是Animal类型,所以是false)24 console.log(a1 instanceof Person) //false(a1也显然不是Person类型,所以同样是false)
Salin selepas log masuk

上面这段代码证明:构造函数模式的确可以做到对象类型的区分。那么该模式是不是已经完美了呢,然而并不是,我们来一起看看下面的代码:

1 //接着上面的代码2 console.log(p1.sayName === a1.sayName) //false
Salin selepas log masuk

发现问题了吗?`p1`的`sayName`竟然和`a1`的`sayName`不是同一个,这说明什么?说明‘构造函数模式’根本就没有‘公用’的概念,创建的每个对象实例都有自己的一套属性和方法,‘属性是私有的’,这个我们可以理解,但方法你都要自己搞一套,这就有点没必要了
明显缺点:上面已经描述了,为了解决这个问题,又出现了一种新模式‘原型模式’,该模式简直就是一个阶段性的跳跃,下面我们来看分一下‘原型模式’

原型模式

这里要记住一句话:构造函数中的属性和方法在每个对象实例之间都不是共享的,都是各自搞一套;而要想实现共享,就要将属性和方法存到构造函数的原型中。这句话什么意思呢?下面我们来详细解释
当建立一个构造函数时(普通函数亦然),会自动生成一个`prototype`(原型),构造函数与`prototype`是一对一的关系,并且此时`prototype`中只有一个`constructor`属性(哪有,明明还有一个`__proto__`呢,这个我们先不在此讨论,后面会有解释)

这个`constructor`是什么?它是一个类似于指针的引用,指向该`prototype`的构造函数,并且该指针在默认的情况下是一定存在的

1 console.log(Person.prototype.constructor === Person) //true
Salin selepas log masuk

刚才说过`prototype`是`自动生成`的,其实还有另外一种手动方式来生成`prototype`:

1 function Person (name) {2   this.name = name3 }4 Person.prototype = {5   //constructor: Person,6   age: 307 }8 console.log(Person.prototype) //Object {age: 30}9 console.log(Person.prototype.constructor === Person) //false
Salin selepas log masuk

Tips:为了证明的确可以为构造函数手动创建`prototype`,这里给`prototype`加了`name`属性。
可能你已经注意到了一个问题,这行代码:

1 console.log(Person.prototype.constructor === Person) //false
Salin selepas log masuk

结果为什么是`false`啊?大哥,刚才的`prototype`是默认生成的,然后我们又用了另外一种方式:手动设置。具体分析一下手动设置的原理:
1.构造函数的`prototype`其实也是一个对象

2.当我们这样设置`prototype`时,其实已经将原先`Person.prototype`给切断了,然后又重新引用了另外一个对象

3.此时构造函数可以找到`prototype`,但`prototype`找不到构造函数了

1 Person.prototype = {2   //constructor: Person, // 因为constructor属性,我没声明啊,prototype就是利用它来找到构造函数的,你竟然忘了声明3   age: 304 }
Salin selepas log masuk

4.所以,要想显示手动设置构造函数的原型,又不失去它们之间的联系,我们就要这样:

1 function Person (name) {2   this.name = name3 }4 Person.prototype = {5   constructor: Person, //constructor一定不要忘了!!6   age: 307 }
Salin selepas log masuk

画外音:“说到这里,你还没有讲原型模式是如何实现属性与方法的共享啊”,不要急,马上开始:

对象实例-构造函数-原型,三者是什么样的关系呢?

看明白这张图的意思吗?
1.当对象实例访问一个属性时(方法依然),如果它自身没有该属性,那么它就会通过`__proto__`这条链去构造函数的`prototype`上寻找
2.构造函数与原型是一对一的关系,与对象实例是一对多的关系,而并不是每创建一个对象实例,就相应的生成一个`prototype`
这就是原型模式的核心所在,结论:在原型上声明属性或方法,可以让对象实例之间共用它们

然后原型模式就是完美的吗?并不是,它有以下两个主要问题:
问题1:如果对象实例有与原型上重名的属性或方法,那么,当访问该属性或方法时,实例上的会屏蔽原型上的

1 function Person (name) {2   this.name = name3 }4 Person.prototype = {5   constructor: Person,6   name: 'lucy'7 }8 var p1 = new Person('jack');9 console.log(p1.name); //jack
Salin selepas log masuk

问题2:由于实例间是共享原型上的属性和方法的,所以当其中一个对象实例修改原型上的属性(基本值,非引用类型值或方法时,其他实例也会受到影响


原因就是,当实例自身的基本值属性与原型上的重名时,实例就会创建该属性,留着今后自己使用,而原型上的属性不会被修改;但如果属性是引用类型值,如:`Array`、`Object`,当发生重名时,实例是不会拷贝一份新的留给自己使用的,还是坚持实例间共享,所以就会出现上图中的情况

以上两个问题就是原型模式的明显缺点,为了改掉这些缺点,我们一般会采用一种组合模式“组合使用构造函数模式和原型模式”,其实在原型模式这一节,该模式已经有所应用了

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

这种模式可谓是集构造函数模式和原型模式之所长,用构造函数模式来定义对象实例的属性或方法,而共享的属性或方法就交给原型模式

 1 function Person (name) { 2   this.name = name //实例的属性,在构造函数中声明 3 } 4  5 Person.prototype = { 6   constructor: Person, 7   sayName: function () { //共享的方法存在原型中 8     alert(this.name) 9   }10 }
Salin selepas log masuk

注:此模式目前是ECMAScript中使用最广泛、认同度最高的一种创建自定义类型的方法

-----------------

下面要介绍的几个模式是针对不同场景的,而不是说`组合使用构造函数模式和原型模式`有什么缺点,又用这几个模式来弥补,不是这样的

动态原型模式

特点:共享的方法是在构造函数中检测并声明的,原型并没有被显示创建

 1 function Person (name) { 2   this.name = name; 3   if (typeof this.sayName !== 'function') { //检查方法是否存在 4     console.log('sayName方法不存在') 5     Person.prototype.sayName = function () { 6       alert(this.name) 7     } 8   } else { 9     console.log('sayName方法已存在')10   }11 }12 13 var p1 = new Person('jack'); //'sayName方法不存在'14 p1.sayName(); //因为sayName不存在,我们来创建它,所以这里输出'jack'15 var p2 = new Person('lucy'); //'sayName方法已存在'16 p2.sayName(); //这时sayName已存在,所以输出'lucy'
Salin selepas log masuk

当`Person`构造函数第一次被调用时,`Person.prototype`上就会被添加`sayName`方法;《Javascript高级程序设计》一书说到:使用动态原型模式时,不能使用对象字面量重写原型。我们来理解一下:

 

分析:
1.`p1`实例创建,此时原型没有`sayName`方法,那我们就为原型添加一个
2.随后,我们以字面量的形式重写了原型,这时旧的原型并没有被销毁,而且它和`p1`还保持着联系
3.之后的实例,也就是这里的`p2`,都是与新原型保持联系;所以`p1`、`p2`有各自的构造器原型,即使它们的构造器是同一个

所以切记:当我们采用动态原型模式时,千万不要以字面量的形式重写原型

寄生构造函数模式

了解此模式之前,我们先来想一个问题:构造函数为什么要用`new`关键字调用?代码说话:

我们发现什么?如果不是`new`方法调用构造函数,那么就要显式的`return`,否则构造函数就不会有返回值;但如果使用`new`,那就没有这个问题了

下面我们再来看寄生构造函数模式:

 1 function Person (name) { 2   var o = new Object(); 3   o.name = name; 4   o.sayName = function () { 5     alert(this.name) 6   }; 7   return o 8 } 9 10 var p1 = new Person('jack'); //与工厂模式唯一不同之处:使用new调用11 p1.sayName(); //jack
Salin selepas log masuk

其实new不new都无所谓,因为我们已经显式的return o

那么寄生构造函数模式到底有什么应用场景呢?据《javascript高级程序设计》一书记载,举例:如果我们想创建一个具有额外方法的特殊数组,那么我们可以这样做:

 1 function SpecialArray () { 2   var values = new Array(); 3   Array.prototype.push.apply(values,arguments); 4     values.toPipedString = function () { 5     return this.join('|') 6   } 7   return values 8 } 9 10 var colors = new SpecialArray('red','blue','green');11 alert(colors.toPipedString()) //'red|blue|green'
Salin selepas log masuk

最后重要的一点:该模式和构造函数和原型无缘,也就是不能区分实例类型,因为该模式生成的实例,它的构造函数都是Object,原型都是Object.prototype

稳妥构造函数模式

该模式与寄生构造函数相比,主要有两点不同:
1.创建对象实例的方法不引用this
2.不使用new操作符调用构造函数
按照稳妥构造函数的要求,可以将前面的Person构造函数重写如下:

1 function Person (name) {2   var o = new Object();3   o.sayName = function () {4     alert(name) //这里其实涉及到了闭包的知识,因此产生了私有属性的概念5   }6   return o7 }
Salin selepas log masuk

此模式最适合在一些安全的环境中(这些环境中会禁止使用this和new),同理,此模式与构造函数和原型也无缘

结语

以上就是对js中创建对象的方式的总结,希望对大家有所帮助

Atas ialah kandungan terperinci JS对象创建常用方式有哪些?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Cara Membuka Segala -galanya Di Myrise
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Analisis fungsi dan prinsip nohup Analisis fungsi dan prinsip nohup Mar 25, 2024 pm 03:24 PM

Analisis peranan dan prinsip nohup Dalam sistem pengendalian seperti Unix dan Unix, nohup ialah arahan yang biasa digunakan yang digunakan untuk menjalankan arahan di latar belakang Walaupun pengguna keluar dari sesi semasa atau menutup tetingkap terminal, arahan itu boleh masih terus dilaksanakan. Dalam artikel ini, kami akan menganalisis fungsi dan prinsip arahan nohup secara terperinci. 1. Peranan nohup: Menjalankan arahan di latar belakang: Melalui arahan nohup, kita boleh membiarkan arahan yang berjalan lama terus dilaksanakan di latar belakang tanpa terjejas oleh pengguna yang keluar dari sesi terminal. Ini perlu dijalankan

Perbincangan mendalam tentang prinsip dan amalan rangka kerja Struts Perbincangan mendalam tentang prinsip dan amalan rangka kerja Struts Feb 18, 2024 pm 06:10 PM

Analisis prinsip dan penerokaan praktikal rangka kerja Struts Sebagai rangka kerja MVC yang biasa digunakan dalam pembangunan JavaWeb, rangka kerja Struts mempunyai corak reka bentuk dan skalabiliti yang baik dan digunakan secara meluas dalam pembangunan aplikasi peringkat perusahaan. Artikel ini akan menganalisis prinsip rangka kerja Struts dan menerokanya dengan contoh kod sebenar untuk membantu pembaca memahami dan menggunakan rangka kerja itu dengan lebih baik. 1. Analisis prinsip rangka kerja Struts 1. Seni bina MVC Rangka kerja Struts adalah berdasarkan MVC (Model-View-Con

Pemahaman mendalam tentang prinsip pelaksanaan Insert batch dalam MyBatis Pemahaman mendalam tentang prinsip pelaksanaan Insert batch dalam MyBatis Feb 21, 2024 pm 04:42 PM

MyBatis ialah rangka kerja lapisan ketekunan Java yang popular yang digunakan secara meluas dalam pelbagai projek Java. Antaranya, sisipan kelompok adalah operasi biasa yang boleh meningkatkan prestasi operasi pangkalan data dengan berkesan. Artikel ini akan meneroka secara mendalam prinsip pelaksanaan Sisipan kelompok dalam MyBatis, dan menganalisisnya secara terperinci dengan contoh kod khusus. Sisipan Batch dalam MyBatis Dalam MyBatis, operasi Sisipan kelompok biasanya dilaksanakan menggunakan SQL dinamik. Dengan membina S yang mengandungi berbilang nilai yang dimasukkan

Tutorial JavaScript Mudah: Cara Mendapatkan Kod Status HTTP Tutorial JavaScript Mudah: Cara Mendapatkan Kod Status HTTP Jan 05, 2024 pm 06:08 PM

Tutorial JavaScript: Bagaimana untuk mendapatkan kod status HTTP, contoh kod khusus diperlukan: Dalam pembangunan web, interaksi data dengan pelayan sering terlibat. Apabila berkomunikasi dengan pelayan, kami selalunya perlu mendapatkan kod status HTTP yang dikembalikan untuk menentukan sama ada operasi itu berjaya dan melaksanakan pemprosesan yang sepadan berdasarkan kod status yang berbeza. Artikel ini akan mengajar anda cara menggunakan JavaScript untuk mendapatkan kod status HTTP dan menyediakan beberapa contoh kod praktikal. Menggunakan XMLHttpRequest

Penjelasan terperinci tentang prinsip pemalam paging MyBatis Penjelasan terperinci tentang prinsip pemalam paging MyBatis Feb 22, 2024 pm 03:42 PM

MyBatis ialah rangka kerja lapisan kegigihan yang sangat baik yang menyokong operasi pangkalan data berdasarkan XML dan anotasi Ia mudah dan mudah digunakan, dan juga menyediakan mekanisme pemalam yang kaya. Antaranya, pemalam paging adalah salah satu pemalam yang lebih kerap digunakan. Artikel ini akan menyelidiki prinsip pemalam paging MyBatis dan menggambarkannya dengan contoh kod khusus. 1. Prinsip pemalam paging MyBatis sendiri tidak menyediakan fungsi paging asli, tetapi anda boleh menggunakan pemalam untuk melaksanakan pertanyaan paging. Prinsip pemalam paging adalah terutamanya untuk memintas MyBatis

Analisis mendalam tentang fungsi dan prinsip kerja perintah chage Linux Analisis mendalam tentang fungsi dan prinsip kerja perintah chage Linux Feb 24, 2024 pm 03:48 PM

Perintah chage dalam sistem Linux ialah perintah yang digunakan untuk mengubah suai tarikh tamat kata laluan akaun pengguna Ia juga boleh digunakan untuk mengubah suai tarikh terpanjang dan terpendek yang boleh digunakan bagi akaun tersebut. Perintah ini memainkan peranan yang sangat penting dalam mengurus keselamatan akaun pengguna dengan berkesan boleh mengawal tempoh penggunaan kata laluan pengguna dan meningkatkan keselamatan sistem. Cara menggunakan arahan chage: Sintaks asas perintah chage ialah: chage [option] nama pengguna Contohnya, untuk mengubah suai tarikh tamat kata laluan pengguna "testuser", anda boleh menggunakan arahan berikut

Perbincangan mendalam tentang fungsi dan prinsip alat RPM Linux Perbincangan mendalam tentang fungsi dan prinsip alat RPM Linux Feb 23, 2024 pm 03:00 PM

Alat RPM (RedHatPackageManager) dalam sistem Linux ialah alat yang berkuasa untuk memasang, menaik taraf, menyahpasang dan mengurus pakej perisian sistem. Ia ialah alat pengurusan pakej yang biasa digunakan dalam sistem RedHatLinux dan juga digunakan oleh banyak pengedaran Linux yang lain. Peranan alat RPM adalah sangat penting Ia membolehkan pentadbir sistem dan pengguna menguruskan pakej perisian dengan mudah pada sistem. Melalui RPM, pengguna boleh memasang pakej perisian baharu dan menaik taraf perisian sedia ada dengan mudah

Prinsip pertaruhan Astar, pembongkaran pendapatan, projek dan strategi airdrop & strategi peringkat pengasuh operasi Prinsip pertaruhan Astar, pembongkaran pendapatan, projek dan strategi airdrop & strategi peringkat pengasuh operasi Jun 25, 2024 pm 07:09 PM

Jadual Kandungan Prinsip Staking Astar Dapp Staking Hasil Pembongkaran Projek Airdrop Berpotensi: AlgemNeurolancheHealthreeAstar Degens DAOVeryLongSwap Staking Strategi & Operasi "AstarDapp Staking" telah dinaik taraf kepada versi V3 pada awal tahun ini, dan banyak pelarasan telah dibuat pada staking peraturan. Pada masa ini, kitaran pertaruhan pertama telah tamat, dan kitaran kecil "pengundian" kitaran pertaruhan kedua baru sahaja bermula. Untuk mendapatkan faedah "ganjaran tambahan", anda perlu memahami peringkat kritikal ini (dijangka akan berlangsung sehingga 26 Jun, berbaki kurang daripada 5 hari). Saya akan memecahkan pendapatan pertaruhan Astar secara terperinci,

See all articles