Day.21 「物件也有继承问题?」 —— JavaScript 继承 与 原型链

「物件也有继承问题?」 —— JavaScript 继承 与 原型链

我们每新增一个函式,浏览器都会向函式内新增一个属性叫 prototype

function Person () {};
console.log( Person.prototype );

prototype

原型链

如果是普通函式的直接调用,prototype 不会有任何作用

当是以构造函式的方式调用,他所新增的物件会有一个隐藏的属性,指向该构造函式的原型物件。
虽然 prototype 是隐藏属性,但我们可以透过 __proto__ 来查看该属性

function Person () {};
const person = new Person;
console.log( person.__proto__ );

proto
原型链

也能发现 prototype__proto__ 是一样的

function Person () {};
const person = new Person;
console.log( Person.prototype === person.__proto__ ); // true

继承

依照之前物件传址的特性,可以了解到物件中,共用的内容,可以设置到 prototype 中,新增的属性就会继承原型物件

function Person () {};
Person.prototype.a = "我是原型物件 a";  // 添加原型物件属性 a
const person = new Person;
console.log( person.a );  // "我是原型物件 a"

继承原型物件 a 属性

可以发现如果物件内没有 a 属性,它就会往原型物件中寻找 a 属性,如果找到就会使用。

function Person () {};
Person.prototype.a = "我是原型物件 a";  // 添加原型物件属性 a
const person = new Person;
person.a = "我是 person 中的 a";
console.log( person.a );  // "我是 person 中的 a"

从本身寻找 a 属性

优化之前的 sayName

看到这里是不是又发现可以更好优化自订物件的方法了!

function Person (name, gender) {
  this.name = name,
  this.gender = gender
}
Person.prototype.sayName = function(){
  console.log( "大家好!我是" + this.name );
}

const person = new Person("毛毛", "男");
person.sayName();  // "大家好!我是毛毛"

就往原型物件寻找 sayName 方法,同时也不会污染到我们的全局作用域!

检查物件属性

有时候,我们会需要检查物件内有没有该属性,可以使用 in 语法来检查:"属性名" in 物件名,需注意属性名要用引号包起来。

function Person (name, gender) {
  this.name = name,
  this.gender = gender
}
Person.prototype.sayName = function(){
  console.log( "大家好!我是" + this.name );
}

const person = new Person("毛毛", "男");
console.log("name" in person);    // true
console.log("sayName" in person); // true

但会发现,会连原型物件的属性也判定为 true
这时如果我们要更确实的判断是不是该物件内的属性,可以使用 hasOwnProperty() 语法来检查

function Person (name, gender) {
  this.name = name,
  this.gender = gender
}
Person.prototype.sayName = function(){
  console.log( "大家好!我是" + this.name );
}

const person = new Person("毛毛", "男");
console.log( person.hasOwnProperty("name"));    // true
console.log( person.hasOwnProperty("sayName")); // false

这些「方法」都哪来的

没错!聪明的你应该已经更了解继承原型链,而我们常用的方法,其实都是在原型物件里面!

function Person () {}
const person = new Person();

console.log( "hasOwnProperty" in person);              // true
console.log( person.hasOwnProperty("hasOwnProperty")); // false

这时尝试使用 __proto__ 找出原型

function Person () {}
const person = new Person();

console.log( person.__proto__.hasOwnProperty("hasOwnProperty")); // false

原型物件中还有原型物件

你会发现,奇怪!怎麽还是 false,那是因为,原型物件也是物件,原型物件中还有原型物件!
当然!这不是无限套娃~会一路找到原型物件为 null 的值,代表该物件没有原型物件了,而这个物件就是 Object 物件的原型

原型物件中还有原型物件

function Person () {}
const person = new Person();

console.log( person.__proto__.__proto__);           // Object
console.log( person.__proto__.__proto__.__proto__); // null
console.log( person.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));  // true

总结

已经把我们的物件精随学习的差不多了~也认识 JavaScript 中,我们常用的方法都藏在物件的隐藏属性之中!


<<:  Day14:插曲(小结)

>>:  大共享时代系列_014_线上白板

【Day 26】Go 与 Redis

这篇之後要来补 QQ 事情是不是越积越多ㄌ Redis redis 是一个 in-memory 的...

DAY22 这边先帮你上一个按钮喔~(四)

「欸!?阿按了这个按钮怎麽没反应阿?」 这是我妈最常问我的问题,大部分情况都是她遥控器忘记装电池。 ...

Day 21:工作术

前言 工作术不只是工作上,还有自己想做的事情,目的都是在一样的时间内做更多事情,且挤出更多时间。 聪...

13 - cheat.sh - 终端机的程序百科全书

在开发时,开发者常常会需要在浏览器上搜寻指令或程序语言相关的说明,藉此来辅助并确保使用的方式正确。但...

[Day 18] 比对首页跟UI的完成度

好的~今天先来检查一下 目前的成品跟一开始规画的UI,完成度如何呢? 比对UI完成度 这是一开始的首...