这篇文章主要介绍了JavaScript中的原型prototype完全解析,prototype可是js界"一切皆对象"论调的重要支撑,讲解了__proto__属性和原型链等干货,需要的朋友可以参考下
要理解JS中的prototype, 首先必须弄清楚以下几个概念
1. JS中所有的东西都是对象
2. JS中所有的东西都由Object衍生而来, 即所有东西原型链的终点指向Object.prototype
// ["constructor", "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", // "propertyIsEnumerable", "__defineGetter__", "__lookupGetter__", "__defineSetter__", // "__lookupSetter__"] console.log(Object.getOwnPropertyNames(Object.prototype));
3. JS中构造函数和实例(对象)之间的微妙关系
构造函数通过定义prototype来约定其实例的规格, 再通过 new 来构造出实例, 他们的作用就是生产对象.
而构造函数(方法)本身又是方法(Function)的实例, 因此也可以查到它的__proto__(原型链)
Object / function F() {} 这样子的就是构造函数啦, 一个是JS原生API提供的, 一个是自定义的
new Object() / new F() 这样子的就是实例啦
实例就"只能"查看__proto__来得知自己是基于什么prototype被制造出来的,
而"不能"再重新定义实例的prototype妄想创造出实例的实例了.
实践出真知, 只有自己动手观察/思考才能真正领悟:
// 先来看看构造函数到底是什么 // function Empty() {} function Empty() {} console.log(Function.prototype, Function.__proto__); // Object {} function Empty() {} console.log(Object.prototype, Object.__proto__); function F() {} // F {} function Empty() {} console.log(F.prototype, F.__proto__);
你可能已经晕了, 我们来分解一下。
prototype prototype输出的格式为: 构造函数名 原型
首先看下Object.prototype输出了什么?
Object {} -> 前面的Object为构造函数的名称, 后面的那个表示原型, 这里是一个{}, 即一个Object对象的实例(空对象)
那么 F {} 我们就明白是什么意思了, F 就是构造函数的名称, 原型也是一个空对象
// 再来看看由构造函数构造出来的实例 var o = new Object(); // var o = {}; // undefined Object {} console.log(o.prototype, o.__proto__); function F() {} var i = new F(); // undefined F {} console.log(i.prototype, i.__proto__);
我们再深入一点, 定义下 F 的原型看看到底会发生些什么?
function F() {} F.prototype.a = function() {}; var i = new F(); // undefined F {a: function} console.log(i.prototype, i.__proto__);
这样我们就清楚的看到 i 是由 F 构造出来的, 原型是 {a: function}, 就是原本的空对象原型新增了一个 a 方法
我们再换一种情况, 完全覆盖 F 的原型会怎么样?
function F() {} F.prototype = { a: function() {} }; var i = new F(); // undefined Object {a: function} console.log(i.prototype, i.__proto__);
咦~ 为什么这里表明 i 是由 Object 构造出来的? 不对吧!
因为我们完全将 F 的prototype覆盖, 其实也就是将原型指定为对象{a: function}, 但这会造成原本的constructor信息丢失, 变成了对象{a: function}指定的constructor.
那么对象{a: function}的constructor是什么呢?
因为对象{a: function}其实就相对于
var o = {a: function() {}} // new了一个Object
那么o的constructor当然是 Object 啦
我们来纠正下这个错误
function F() {} F.prototype = { a: function() {} } // 重新指定正确的构造函数 F.prototype.constructor = F; var i = new F(); // undefined F {a: function, constructor: function} console.log(i.prototype, i.__proto__);
现在又能得到正确的原型信息了~
原型链
然后来看看什么原型链又是个什么东西?
简单的来讲和OOP中的继承关系(链)是一样的, 一层一层往上找, 直至最终的 Object.prototype
最最关键的是要弄清楚JS中哪些东西是(实例)对象, 这个简单了, JS中所有东西都是对象!
再要弄清楚就是任何一个对象都是有一个原型的!
那么我们来证明一下:
Object // 这是一个函数, 函数是 Function 的实例对象, 那么就是由 Function 构造出来的 Object.__proto__ == Function.prototype // 那么Object的原型, true // 这个是一个普通对象了, 因此属于 Object 的实例 Function.prototype.__proto__ == Object.prototype // true // 这已经是原型链的最顶层了, 因此最终的指向 null Object.prototype.__proto__ == null // true Function // 这也是一个函数, 没错吧! Function.__proto__ == Function.prototype // true function A() {} // 这是一个自定义的函数, 终归还是一个函数, 没错吧! A.__proto__ == Function.prototype // 任何函数都是 Function 的实例, 因此A的原型是? var a = new A() a.__proto__ == A.prototype // 实例a是由A构造函数构造出来的, 因此a的原型是由A的prototype属性定义的 A.prototype.__proto__ == Object.prototype // 普通对象都是 Object 的示例
Prototype和__proto__每一个对象都包含一个__proto__,指向这个的对象的“原型”。
类似的事情是,每一个函数都包含一个prototype,这个prototype对象干什么的了?
咱们看看如下代码,用构造函数来创建一个对象(上面是用字面量的形式创建对象)。
function Foo(){}; var foo = new Foo(); console.log(foo.__proto__);
试想想,这个foo对象的__proto__会指向什么?
一个包含constructor属性的对象?看不太懂没关系,把函数Foo的prototype属性打印出来,对比一下就知道了。
function Foo(){}; var foo = new Foo(); console.log(foo.__proto__); console.log(Foo.prototype); console.log(foo.__proto__ === Foo.prototype);
原来,new出来的对象foo的__proto__就只指向函数Foo的prototype。
foo.__proto__ --> Foo.prototype
JS这么设计有何意义了?回忆下上面说的,在JS的世界中,对象不是根据类(模具)创建出来的,而是从原型(另一个对象)衍生出来的。
当我们执行new操作创建一个新的对象时,先不深入new操作的具体实现,但有一点我们是肯定的——就是为新对象的__proto__指向一个原型对象。
就刚才这段代码
function Foo(){}; var foo = new Foo();
foo.__proto__到底要指向谁了?你怎么不能指向Foo这个函数本身吧,虽然函数也是对象,这个有机会会详细讲。但如何foo.__proto__指向Foo固然不合适,因为Foo是一个函数,有很多逻辑代码,foo作为一个对象,继承逻辑处理没有任何意义,它要继承的是“原型对象”的属性。
所以,每个函数会自动生成一个prototype对象,由这个函数new出来的对象的__proto__就指向这个函数的prototype。
foo.__proto__ --> Foo.prototype
总结说了这么多,感觉还是没完全说清楚,不如上一张图。我曾经参考过其他网友的图,但总觉得哪里没说清楚,所以我自己画了一张图,如果觉得我的不错,请点个赞!(老子可是费了牛劲才画出来)。
咱们就着这张图,记住如下几个事实:
1. 每个对象中都有一个_proto_属性。
JS世界中没有类(模具)的概念,对象是从另一个对象(原型)衍生出来的,所以每个对象中会有一个_proto_属性指向它的原型对象。(参考左上角的那个用字面量形式定义的对象obj,它在内存中开辟了一个空间存放对象自身的属性,同时生成一个_proto_指向它的原型——顶层原型对象。)
2. 每个函数都有一个prototype属性。
“构造函数”为何叫构造函数,因为它要构造对象。那么根据上面第一条事实,构造出来的新对象的_proto_属性指向谁了?总不能指向构造函数自身,虽然它也是个对象,但你不希望新对象继承函数的属性与方法吧。所以,在每个构造函数都会有一个prototype属性,指向一个对象作为这个构造函数构造出来的新对象的原型。
3. 函数也是对象。
每个函数都有一些通用的属性和方法,比如apply()/call()等。但这些通用的方法是如何继承的呢?函数又是怎么创建出来的呢?试想想,一切皆对象,包括函数也是对象,而且是通过构造函数构造出来的对象。那么根据上面第二条事实,每个函数也会有_proto_指向它的构造函数的prototype。而这个构造函数的函数就是Function,JS中的所有函数都是由Function构造出来的。函数的通用属性与方法就存放在Function.prototype这个原型对象上。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
全面分析JavaScript面向对象概念中的Object类型与作用域(附有示例)
详细解读JavaScript设计模式开发中的桥接模式(高级篇)
Atas ialah kandungan terperinci 在JavaScript中对原型prototype全面分析. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Python dan JavaScript mempunyai kelebihan dan kekurangan mereka sendiri dari segi komuniti, perpustakaan dan sumber. 1) Komuniti Python mesra dan sesuai untuk pemula, tetapi sumber pembangunan depan tidak kaya dengan JavaScript. 2) Python berkuasa dalam bidang sains data dan perpustakaan pembelajaran mesin, sementara JavaScript lebih baik dalam perpustakaan pembangunan dan kerangka pembangunan depan. 3) Kedua -duanya mempunyai sumber pembelajaran yang kaya, tetapi Python sesuai untuk memulakan dengan dokumen rasmi, sementara JavaScript lebih baik dengan MDNWebDocs. Pilihan harus berdasarkan keperluan projek dan kepentingan peribadi.

Peralihan dari C/C ke JavaScript memerlukan menyesuaikan diri dengan menaip dinamik, pengumpulan sampah dan pengaturcaraan asynchronous. 1) C/C adalah bahasa yang ditaip secara statik yang memerlukan pengurusan memori manual, manakala JavaScript ditaip secara dinamik dan pengumpulan sampah diproses secara automatik. 2) C/C perlu dikumpulkan ke dalam kod mesin, manakala JavaScript adalah bahasa yang ditafsirkan. 3) JavaScript memperkenalkan konsep seperti penutupan, rantaian prototaip dan janji, yang meningkatkan keupayaan pengaturcaraan fleksibiliti dan asynchronous.

Enjin JavaScript yang berbeza mempunyai kesan yang berbeza apabila menguraikan dan melaksanakan kod JavaScript, kerana prinsip pelaksanaan dan strategi pengoptimuman setiap enjin berbeza. 1. Analisis leksikal: Menukar kod sumber ke dalam unit leksikal. 2. Analisis Tatabahasa: Menjana pokok sintaks abstrak. 3. Pengoptimuman dan Penyusunan: Menjana kod mesin melalui pengkompil JIT. 4. Jalankan: Jalankan kod mesin. Enjin V8 mengoptimumkan melalui kompilasi segera dan kelas tersembunyi, Spidermonkey menggunakan sistem kesimpulan jenis, menghasilkan prestasi prestasi yang berbeza pada kod yang sama.

Aplikasi JavaScript di dunia nyata termasuk pengaturcaraan sisi pelayan, pembangunan aplikasi mudah alih dan Internet of Things Control: 1. Pengaturcaraan sisi pelayan direalisasikan melalui node.js, sesuai untuk pemprosesan permintaan serentak yang tinggi. 2. Pembangunan aplikasi mudah alih dijalankan melalui reaktnatif dan menyokong penggunaan silang platform. 3. Digunakan untuk kawalan peranti IoT melalui Perpustakaan Johnny-Five, sesuai untuk interaksi perkakasan.

Saya membina aplikasi SaaS multi-penyewa berfungsi (aplikasi edTech) dengan alat teknologi harian anda dan anda boleh melakukan perkara yang sama. Pertama, apakah aplikasi SaaS multi-penyewa? Aplikasi SaaS Multi-penyewa membolehkan anda melayani beberapa pelanggan dari Sing

Artikel ini menunjukkan integrasi frontend dengan backend yang dijamin oleh permit, membina aplikasi edtech SaaS yang berfungsi menggunakan Next.Js. Frontend mengambil kebenaran pengguna untuk mengawal penglihatan UI dan memastikan permintaan API mematuhi dasar peranan

JavaScript adalah bahasa utama pembangunan web moden dan digunakan secara meluas untuk kepelbagaian dan fleksibiliti. 1) Pembangunan front-end: Membina laman web dinamik dan aplikasi satu halaman melalui operasi DOM dan kerangka moden (seperti React, Vue.js, sudut). 2) Pembangunan sisi pelayan: Node.js menggunakan model I/O yang tidak menyekat untuk mengendalikan aplikasi konkurensi tinggi dan masa nyata. 3) Pembangunan aplikasi mudah alih dan desktop: Pembangunan silang platform direalisasikan melalui reaktnatif dan elektron untuk meningkatkan kecekapan pembangunan.

Trend terkini dalam JavaScript termasuk kebangkitan TypeScript, populariti kerangka dan perpustakaan moden, dan penerapan webassembly. Prospek masa depan meliputi sistem jenis yang lebih berkuasa, pembangunan JavaScript, pengembangan kecerdasan buatan dan pembelajaran mesin, dan potensi pengkomputeran IoT dan kelebihan.


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Dreamweaver Mac版
Alat pembangunan web visual

SublimeText3 versi Inggeris
Disyorkan: Versi Win, menyokong gesaan kod!

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

Muat turun versi mac editor Atom
Editor sumber terbuka yang paling popular

Penyesuai Pelayan SAP NetWeaver untuk Eclipse
Integrasikan Eclipse dengan pelayan aplikasi SAP NetWeaver.