深入探索 JavaScript 原型链:解密 JavaScript 中原型的神秘力量
前言
原型
是函数上的一个属性,它定义了构造函数制造的对象的公共祖先。
原型链
js引擎在查找属性时,会顺着对象的隐式原型(这个在下面会进行介绍)向上查找,找不到则查找隐式原型的隐式原型,一直向上,直到找到null为止,这种查找关系称之为原型链。
正文
原型
Person.prototype.lastName = 'lt';
Person.prototype.say = function() {
console.log('素~');
}
function Person() {
this.name = 'lxp';
}
let p1 = new Person(); //隐式具有 lastName say
console.log(p1);
console.log(p1.lastName);
p1.say();
分析
定义了一个p1对象,该对象会继承构造函数Person内的name属性(显式属性),并且p1的原型会继承构造函数Person的原型(隐式原型),所以当查找lastName属性时会先先查找p1的显示属性中有没有,如果没有就会查找隐式原型中有没有该属性。
Car.prototype.name = 'su7';
Car.prototype.height = 1400;
Car.prototype.lang = 5000;
function Car(color, owner) {
this.color = color;
this.owner = owner;
}
let ltt = new Car('black', 'ltt');
let lxp = new Car('purple', 'lxp');
console.log(ltt.name);
分析
对于构造函数Car,我们会把它的name,lang,height(因为Car的这些属性是设定好的)放在它的原型上,然后它的name和owner会通过接收两个参数来实现。
Car.prototype.producter = 'xiaomi'
function Car() {
this.name = 'su7';
}
let car = new Car();
console.log(car);
console.log(car.producter);
添加代码
car.name = '红旗';
car.producter = 'huawei';
可以打开一个网页,在控制台运行代码来查看原型上的nickname是否改变。显然是没有改变的
分析
实例对象可以修改显示继承到的属性,但是无法修改隐式继承到的属性(原型上的)。
添加代码
car.nickname = 'ltt';
Car.prototype.nickname = 'ltt';
分析
实例对象无法给原型新增属性。
添加代码
delete car.producter;
delete Car.prototype.producter;
分析
实例对象无法删除原型上的属性。
总结
构造函数new出来的对象会隐式继承到构造函数原型上的属性。
- 实例对象可以修改显示继承到的属性,但是无法修改隐式继承到的属性(原型上的);
- 实例对象无法给原型新增属性;
- 实例对象无法删除原型上的属性。
function Bus() {}
Car.prototype = {
constructor: Bus
}
function Car() {
}
let car = new Car();
console.log(car.constructor); //记录该对象是由谁创建的
分析
constructor是记录该对象由谁创建的。
原型链
创建一个html,便于去控制台查看
<script>
function Person() {
}
let p =new Person();
console.log(Person.prototype);//函数原型 显式原型
console.log(p.__proto__); // p.__proto__ 对象的原型 隐式原型
//Person.prototype === p.__proto__
//Person.prototype.__proto__ === object.prototype
//object.prototype.__proto__ ===
</script>
分析
Person.prototype(函数原型 显式原型) === p.__proto__(对象的原型 隐式原型)
Person.prototype.__proto__ === object.prototype
总结
-
对象的隐式原型 === 创建它的构造函数的显示原型
-
js引擎在查找属性时,会先查找对象显示具有的属性,找不到,再查找对象的隐式原型(
__proto__
)
GrandFather.prototype.say = function() {
console.log('haha');
}
function GrandFather() {
this.age = 60;
this.like = 'drink';
}
Father.prototype = new GrandFather();
function Father() {
this.age = 40;
this.fortune = {
card: 'visa'
}
}
Son.prototype = new Father();
function Son() {
this.age = 18;
}
let son =new Son();
测试代码
console.log(son.age);//18
测试代码
console.log(son.fortune);
测试代码
console.log(son.like);
测试代码
son.say();
总结
js引擎在查找属性时,会顺着对象的隐式原型向上查找,找不到则查找隐式原型的隐式原型,一直向上,直到找到null为止,这种查找关系称之为原型链。
结语
最后让我们来思考一个问题:所有的对象都有原型? 答案:不 Object.create(null) 没有原型。
实例
创建一个html
<script>
let a ={
name:'ltt'
}
let obj = Object.create(a);//创建一个新对象,让新对象隐式继承 a 对象的属性
console.log(obj);
</script>
分析
Object.create(a) 创建一个新对象,让新对象隐式继承 a 对象的属性。
添加代码
let obj1 = Object.create(null);//该对象没有原型
console.log(obj1);
分析
Object.create(null)创建的对象没有原型。
转载自:https://juejin.cn/post/7366076727566106676