Artikel ini membawa anda pengetahuan tentang pewarisan dan rantaian prototaip dalam javascript, termasuk isu yang berkaitan dengan pembina, prototaip dan gula sintaks kelas. Saya harap ia dapat membantu semua orang.
2. Pembina
2.2 Proses instantiating objek
//创造一个构造函数let Father = function(name,age){ //实例成员 this.name = name; this.age = age; this.method = "我是一个实例成员";} //静态成员Father.like = "mother"; //检验实例对象是否能够被构造函数直接访问console.log(Father.method); //undefinedconsole.log(Father.like); //mother //实例化一个对象let father = new Father("小王",27); //检验静态对象是否能够被实例化对象访问console.log(father.name); //小王console.log(father.age); //27console.log(father.like); //undefined
(1) Buat objek kosong anak {}
(2) Sediakan sambungan rantai prototaip untuk anak lelaki( 3) Ikat semula ini supaya this of the constructor menghala ke objek baharu son.__proto__ = Father.prototype
(4) Berikan nilai kepada sifat objek baharu Father.call(this)
(5) Kembalikan ini son.name
, Pada masa ini, objek baharu mempunyai kaedah dan sifat pembina
Satu soalan kecil: Adakah semua kaedah instantiating objek dikongsi? return this
Anda boleh menemuinya fungsi Kaedah yang ditakrifkan secara langsung secara dalaman akan memperuntukkan ruang ingatan baharu kepada kaedah ini setiap kali objek baharu diwujudkan, manakala kaedah yang ditambah melalui prototaip akan berkongsi ruang.
//函数内部直接定义的方法let Father = function(){ this.read = function(){ console.log("我是内部定义的read方法!"); }}//通过Analisis ringkas tentang warisan JavaScript dan rantaian prototaip添加的方法Father.prototype.look = function(){ console.log("我是通过Analisis ringkas tentang warisan JavaScript dan rantaian prototaip定义的look方法!");} //实例化对象进行检验let father1 = new Father();let father2 = new Father(); father1.read(); //我是内部定义的read方法!father2.read(); //我是内部定义的read方法!console.log(father1.read === father2.read); //falsefather1.look(); //我是通过Analisis ringkas tentang warisan JavaScript dan rantaian prototaip定义的look方法!father2.look(); //我是通过Analisis ringkas tentang warisan JavaScript dan rantaian prototaip定义的look方法!console.log(father1.look === father2.look); /true
Jadi kita boleh meringkaskan peraturan asas untuk menentukan pembina, iaitu,
atribut awam ditakrifkan kepada Dalam pembina, kami meletakkan kaedah awam pada objek prototaip.let Father = function(name){ this.name = name;}let father1 = new Father("小王"); let father2 = new Father("小红"); console.log(father1.name === father2.name); //falselet father1 = new Father("小王"); let father2 = new Father("小王"); console.log(father1.name === father2.name); //true
3. Prototaip
dan ia tidak akan menggambarkan kaedah membuka storan ruang.
3.3 Di manakah titik ini dalam prototaip Father.prototype.method
4. Rantaian Prototaip
__proto__
__proto__
Function.__proto__
4.2 Aplikasi rantai prototaip Object.prototype.__proto__
dan setiap objek mempunyai Digabungkan dengan titik-titik yang ditulis di bahagian atas, ia sepatutnya tidak menjadi masalah besar untuk memahami gambar di atas, bulatan dalam gambar Bahagian atas ialah rantai prototaip yang mengerikan. __proto__
__proto__
4.4 Cara mencari rantai prototaip
let Father = function(name){ this.name = name;}let father = new Father("老王");console.log(father.__proto__ === Father.prototype); //true //验证上述说法中的第二条
(2) Jika tiada kaedah tarian, pergi ke prototaip objek prototaip pembina untuk mencari kaedah tarian.
(3) Jika tiada kaedah tarian, pergi ke prototaip objek prototaip Objek untuk mencari kaedah tarian. (4) Jika tiada lagi, ralat akan dilaporkan.有两种添加方法,第一种为上面的写法,直接通过 构造函数.prototype.方法名 进行添加;第二种为重定义构造函数的prototype,但是此种情况会丢失掉原有的constructor构造器,所以一定要再连接回去,例子如下:
function Star(name) { this.name = name;}Star.prototype = { dance:function(){ console.log("重定义prototype"); }}Star.prototype.constructor = Star;
另外,类似于Array、String这些内置的类是不能这么处理的。
这里就长话短说,首先我们要明确继承需要继承哪些东西,在前文中我们提到了定义构造函数的基本规则,即**公共属性定义到构造函数里面,公共方法我们放到原型对象身上。**我们所需要继承的东西也不外乎就这二者,公共属性的继承可以通过call()或者apply()进行this的指向定义,而公共方法可以通过原型对象的赋值进行处理,因此我们很容易想到如下的方法:
//定义一个父类function Father(name) { this.name = name;}Father.prototype.dance = function () { console.log('I am dancing');};//定义一个子类function Son(name, age) { Father.call(this, name); this.age = age;}//通过赋值的方法连接Son.prototype = Father.prototype;//为子类添加方法Son.prototype.sing = function () { console.log('I am singing');}; let son = new Son('小红', 100); //此时父类也被影响了console.log(Father.prototype) //{dance: ƒ, sing: ƒ, constructor: ƒ}
很显然,当我们只想修改子类里面的方法时,显然上述方法不太合适;因此 我们可以尝试new一个新的父类出来,代码如下:
function Father(name) { this.name = name;}Father.prototype.dance = function () { console.log('I am dancing');};function Son(name, age) { Father.call(this, name); this.age = age;}Son.prototype = new Father();Son.prototype.sing = function () { console.log('I am singing');};let son = new Son('小红', 100);console.log(Father.prototype) //{dance: ƒ, constructor: ƒ}
对于以前了解过面向对象编程的程序员来讲,上述关于继承的写法属实让人有些难以接受,因此在es6里面新增了一个语法糖来更方便更便捷地书写继承,这里就直接上代码了;
class Father { constructor(name) { this.name = name; } dance() { console.log("我是" + this.name + ",我今年" + this.age + "岁," + "我在跳舞"); }}class Son extends Father { constructor(name, age) { super(name); this.age = age; } sing() { console.log("我是" + this.name + ",我今年" + this.age + "岁," + "我在唱歌"); }}let obj = new Son('小红', 19); obj.sing();obj.dance();
分析一下上面代码,首先一个类(构造函数)里面依旧为两部分,即公共属性和公共方法,constructor() 里面存放了该构造函数的公共属性,后面接着的便是公共方法,extends 关键字表示继承的是哪个类,super() 便是将里面父类里面相应的公共属性拿出来,这样看下来便可以将代码规整许多。
相关推荐:javascript学习教程
Atas ialah kandungan terperinci Analisis ringkas tentang warisan JavaScript dan rantaian prototaip. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!