掘金 后端 ( ) • 2024-05-08 10:57

theme: geek-black

前言

原型

是函数上的一个属性,它定义了构造函数制造的对象的公共祖先

原型链

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();

image.png

分析

定义了一个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);

image.png

分析

对于构造函数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);

image.png

添加代码

car.name = '红旗';
car.producter = 'huawei';

image.png

可以打开一个网页,在控制台运行代码来查看原型上的nickname是否改变。显然是没有改变的

image.png

分析

实例对象可以修改显示继承到的属性,但是无法修改隐式继承到的属性(原型上的)。

添加代码

car.nickname = 'ltt';

image.png

Car.prototype.nickname = 'ltt';

image.png

分析

实例对象无法给原型新增属性。

添加代码

delete car.producter;

image.png

delete Car.prototype.producter;

image.png

分析

实例对象无法删除原型上的属性。

总结

构造函数new出来的对象会隐式继承构造函数原型上的属性

  1. 实例对象可以修改显示继承到的属性,但是无法修改隐式继承到的属性(原型上的)
  2. 实例对象无法给原型新增属性;
  3. 实例对象无法删除原型上的属性。
function Bus() {}
Car.prototype = {
    constructor: Bus
}

function Car() {

}

let car = new Car();
console.log(car.constructor); //记录该对象是由谁创建的

image.png

分析

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>

image.png

image.png 分析

  • 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

image.png 测试代码

console.log(son.fortune);

image.png 测试代码

console.log(son.like);

image.png 测试代码

son.say();

image.png

总结

js引擎在查找属性时,会顺着对象的隐式原型向上查找,找不到则查找隐式原型的隐式原型,一直向上,直到找到null为止,这种查找关系称之为原型链。

结语

最后让我们来思考一个问题:所有的对象都有原型? 答案:不 Object.create(null) 没有原型。

实例

创建一个html

<script>
    let a ={
        name:'ltt'
    }
    let obj = Object.create(a);//创建一个新对象,让新对象隐式继承 a 对象的属性
    console.log(obj);
</script>

image.png 分析

Object.create(a) 创建一个新对象,让新对象隐式继承 a 对象的属性。

添加代码

 let obj1 = Object.create(null);//该对象没有原型
 console.log(obj1);

image.png

分析

Object.create(null)创建的对象没有原型。

image.png