导语
说到 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 属性,为什么能够正常打印?这就涉及到继承(如图)
person1 本身是没有 name 属性的,但是通过 _ proto _ 这条原型链可以往上找,找到构造函数 Person(),从而拿到 name 属性。
原型链查找规则
如果我们在实例 person1 上再去添加一个 name 属性,如下:
let person1 = new Person(); person1.name= "养猪的刘某人"; console.log(name) // 养猪的刘某人
我们会发现打印变成了 “养猪的刘某人”,这就是就近原则:程序运行的时候,先在对象基本属性中查找,如果找不到,顺着原型链往上找。看到这个图,是不是新建的 name 离 person1 近一些:
那有的同学可能又要问了,那我怎么判断这个属性是对象的基本属性还是通过原型链查找的呢?那就要用到 hasOwnProperty(), 我们可以这么做:
// 建一个基本属性 person1.a = "person1基本属性"; let item; for(item in person1){ // 基本的 if(person1.hasOwnProperty(item)){ console.log(item); // a } }
那又有同学懵逼了,这个**hasOwnProperty()**哪里来的?person1 也没有,Person()也没有,不要急,如图:
是不是一目了然?person1 顺着原型链找到 Person()的原型,然后没找到,那怎么办,继续往上找。
找到Person的原型链,指向Object的原型。这个时候找到了hasOwnProperty(),从而继承这个方法(通过原型链)。
FAQ : _proto_指向创建它的函数的prototype
那如果还没有呢?顺着原型链一级一级往上找,知道找到 null 为止。如果没有,报错,这就是原型链的查找规则。