深入了解js原型与原型链——继承

简介: 说到 js原型、原型链、继承,是个令人头疼的问题,说懂吧,只懂一点,说不懂,倒是知道一点。看到网上很多关于这几个知识点的文章,不过大都会把人讲懵,今天你刷到我,那么你就舒服了。

导语



说到 js原型、原型链、继承,是个令人头疼的问题,说懂吧,只懂一点,说不懂,倒是知道一点。

看到网上很多关于这几个知识点的文章,不过大都会把人讲懵,今天你刷到我,那么你就舒服了。


js 原型


话不多说,先上代码:

function Person(){
 }
 Person.prototype.name = "养猪的王某人";
 Person.prototype.age = 18;
 Person.prototype.getAge = function (){
      console.log(this.age);
 }

1.这段代码非常简单,定义了一个函数Person(),在其原型上定义了属性与方法

 let person1 = new  Person();
 console.log(Person.prototype); //  Object
 console.log(person1);  // undefined

2.新建一个Person的实例对象:person1 。从上代码可知,函数拥有prototype,而普通对象没有


原型链与继承


console.log(person1.name);  // 养猪的王某人
person1.getAge()  // 控制台打印:18

这里出现了一个问题:person1 并没有 name 属性,为什么能够正常打印?这就涉及到继承(如图)

1.png

person1 本身是没有 name 属性的,但是通过 _ proto _ 这条原型链可以往上找,找到构造函数 Person(),从而拿到 name 属性。


原型链查找规则


如果我们在实例 person1 上再去添加一个 name 属性,如下:

let person1 = new  Person();
person1.name= "养猪的刘某人";
console.log(name) // 养猪的刘某人

我们会发现打印变成了 “养猪的刘某人”,这就是就近原则:程序运行的时候,先在对象基本属性中查找,如果找不到,顺着原型链往上找。看到这个图,是不是新建的 name 离 person1 近一些:

2.png

那有的同学可能又要问了,那我怎么判断这个属性是对象的基本属性还是通过原型链查找的呢?那就要用到 hasOwnProperty(), 我们可以这么做:

 // 建一个基本属性
 person1.a = "person1基本属性";
 let item;
 for(item in person1){
     // 基本的
     if(person1.hasOwnProperty(item)){
         console.log(item); // a
     }
 }

那又有同学懵逼了,这个**hasOwnProperty()**哪里来的?person1 也没有,Person()也没有,不要急,如图:

3.png

是不是一目了然?person1 顺着原型链找到 Person()的原型,然后没找到,那怎么办,继续往上找。

找到Person的原型链,指向Object的原型。这个时候找到了hasOwnProperty(),从而继承这个方法(通过原型链)。

FAQ : _proto_指向创建它的函数的prototype

那如果还没有呢?顺着原型链一级一级往上找,知道找到 null 为止。如果没有,报错,这就是原型链的查找规则。


目录
相关文章
|
20天前
|
JavaScript 前端开发
js开发:请解释原型继承和类继承的区别。
JavaScript中的原型继承和类继承用于共享对象属性和方法。原型继承通过原型链实现共享,节省内存,但不支持私有属性。
19 0
|
1月前
|
JavaScript 前端开发
JavaScript 继承的方式和优缺点
JavaScript 继承的方式和优缺点
13 0
|
JavaScript 前端开发 Java
深入JS面向对象(原型-继承)(三)
深入JS面向对象(原型-继承)
31 0
|
JavaScript 前端开发 Java
深入JS面向对象(原型-继承)(一)
深入JS面向对象(原型-继承)
32 0
|
2天前
|
JavaScript 前端开发
在JavaScript中,函数原型(Function Prototype)是一个特殊的对象
JavaScript中的函数原型是一个特殊对象,它为所有函数实例提供共享的方法和属性。每个函数在创建时都有一个`prototype`属性,指向原型对象。利用原型,我们可以向所有实例添加方法和属性,实现继承。例如,我们定义一个`Person`函数,向其原型添加`greet`方法,然后创建实例`john`和`jane`,它们都能调用这个方法。尽管可以直接在原型上添加方法,但推荐在构造函数内部定义以封装数据和逻辑。
8 2
|
4天前
|
JavaScript 前端开发
JavaScript 中最常用的继承方式
JavaScript中的继承有多种实现方式:1) 原型链继承利用原型查找,但属性共享可能引发问题;2) 借用构造函数避免共享,但方法复用不佳;3) 组合继承结合两者优点,是最常用的方式;4) ES6的class继承,是语法糖,仍基于原型链,提供更直观的面向对象编程体验。
9 1
|
4天前
|
设计模式 JavaScript 前端开发
在JavaScript中,继承是一个重要的概念
JavaScript继承有优点和缺点。优点包括代码复用、扩展性和层次结构清晰。缺点涉及深继承导致的复杂性、紧耦合、单一继承限制、隐藏父类方法以及可能的性能问题。在使用时需谨慎,并考虑其他设计模式。
9 2
|
5天前
|
JavaScript 前端开发 开发者
JavaScript 继承的方式和优缺点
JavaScript 继承的方式和优缺点
9 0
|
13天前
|
JavaScript 前端开发
JavaScript 继承的方式和优缺点
JavaScript 继承的方式和优缺点
|
14天前
|
JavaScript 前端开发 开发者
【专栏】JavaScript 中的 prototype 和__proto__是关乎对象继承和属性查找的关键概念
【4月更文挑战第29天】JavaScript 中的 prototype 和__proto__是关乎对象继承和属性查找的关键概念。prototype 是函数属性,用于实现对象继承,方法和属性定义在其上可被所有实例共享。__proto__是对象属性,实现属性查找机制,当对象自身找不到属性时,会沿原型链向上查找。两者关系:__proto__指向构造函数的 prototype,构成对象与原型的桥梁。虽然 prototype 可直接访问,但__proto__由引擎内部维护,不可见。理解两者区别有助于深入学习 JavaScript。