欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > js原型和原型链

js原型和原型链

2025/11/9 6:51:50 来源:https://blog.csdn.net/qq_48795482/article/details/147201482  浏览:    关键词:js原型和原型链

js原型:

1、原型诞生的目的是什么呢?

js原型的产生是为了解决在js对象实例之间共享属性和方法,并把他们很好聚集在一起(原型对象上)。每个函数都会创建一个prototype属性,这个属性指向的就是原型对象。

2、理解原型

无论何时,只要创建一个函数,就会为这个函数添加一个属性prototype,这个属性指向一个对象——原型对象。原型对象默认只有一个属性constructor(不可枚举属性),这个属性指回构造函数,另外其他的属性和方法都继承自Object.prototype。

构造函数通过new关键字调用创建对象实例。对象实例会有一个[[prototype]]属性指向函数的原型对象,js访问的话就是通过obj.__proto__指向构造函数原型对象。

注意:对象实例和构造函数之间没有直接的联系。但是通过对象实例obj.constructor是指向构造函数的,这是因为对象实例本身是没有constructor这个属性的,但是沿着原型链查找会找到原型上constructor是指向构造函数的。

关系图如上。

Person === Person.prototype.constructor //trueperson.__proto__ === Person.prototype //true

可以看出,构造函数和函数原型是循环引用的关系。

3、几个关于原型的方法:

isPrototypeOf(): 对象实例上的方法,继承自Object.prototype

Person.prototype.isPrototypeOf(person)    //true

Object.getPrototypeOf():可以方便的获取一个对象的原型。

Object.getPrototypeOf(person)===Person.prototype  //true

Object.setPrototypeOf()和Object.create():设置对象的原型

1. Object.setPrototypeOf(obj, prototype)

  • 功能: 用于设置一个现有对象的原型。
  • 参数:
    • obj: 目标对象,其原型将被修改。
    • prototype: 要设置为目标对象原型的新对象(或 null)。
  • 返回值: 返回被修改的对象 obj
  • 用法:
    const obj = {};
    const proto = { greet: () => console.log('Hello!') };Object.setPrototypeOf(obj, proto);obj.greet(); // 输出: Hello!
  • 特点:
    • 修改的是现有对象的原型。
    • 如果目标对象的原型已经被设置为某个值,Object.setPrototypeOf() 会覆盖它。
    • 可能会影响性能,因为设置原型会破坏某些 JavaScript 引擎的优化。

2. Object.create(proto, [propertiesObject])

  • 功能: 创建一个新对象,并将该对象的原型设置为指定的对象。
  • 参数:
    • proto: 新对象的原型对象(或 null)。
    • propertiesObject(可选): 一个对象,其属性描述符用于定义新对象的自身属性。
  • 返回值: 返回一个新对象,其原型是 proto
  • 用法:
    const proto = { greet: () => console.log('Hello!') };
    const obj = Object.create(proto);obj.greet(); // 输出: Hello!
  • 特点:
    • 创建的是新对象,不会修改现有对象。
    • 更适合用于继承或创建具有特定原型的对象。
    • 性能通常优于 Object.setPrototypeOf(),因为它是专门为创建对象而设计的。

4、原型对象属性和对象实例属性的优先级

如果对象实例上定义了和原型对象上同名的属性,那么对象实例的属性会覆盖掉原型对象上的属性。

hasOwnProperty():对象实例上继承自Object.prototype上的方法。区分属性是在对象原型上还是对象实例上。

const obj = Object.create({ inheritedProp: 'value' });
obj.ownProp = 'myValue';console.log(obj.hasOwnProperty('ownProp')); // true
console.log(obj.hasOwnProperty('inheritedProp')); // false

in操作符:当你需要检查属性是否存在于对象中(无论是自身属性还是继承属性)时,使用 in

const obj = Object.create({ inheritedProp: 'value' });
obj.ownProp = 'myValue';console.log('ownProp' in obj); // true
console.log('inheritedProp' in obj); // true

5、关于自定义原型特别需要注意的问题

A)重写原型会切断原型对象和构造函数之间的联系,需要手动重新建立。给原型对象增加constructor属性(且不可枚举),指回构造函数。

function Person(name,age){this.name=name;this.age=age;
}Person.prototype={name:'myName',age:99,job:'myjob',sayName(){console.log(this.name)}
}Object.defineProperty(Person.prototype,'constructor',{value:Person
})

B)重写原型之前,使用构造方法创建出来的对象实例的__proto__指向的还是原来的原型对象。重写原型之后,再次创建出来的对象__proto__指向的才是新的原型对象。

function Person(name,age){this.name=name;this.age=age;
}let person1=new Person('zhangsan',18)Person.prototype={name:'myName',age:99,job:'myjob',sayName(){console.log(this.name)}
}Object.defineProperty(Person.prototype,'constructor',{value:Person
})let person2=new Person('lisi',19)console.log(person1)
console.log(person2)

根据需要,可以将先前的创建对象实例的原型重新指定一下。

6、原型存在的问题

共享引用值的问题,如下:

function Person(name,age){this.name=name;this.age=age;
}
Person.prototype.friends=['a','b','c','d']let person1=new Person('zhangsan',18)
let person2=new Person('lisi',19)person1.friends.splice(1,1)
console.log(person1.friends)
console.log(person2.friends)

person1的friends少了一个,person2也跟着少了一个,像这种问题其实也不算问题。把friends属性变成对象实例自有的属性即可。

原型链:

1、理解原型链

理解了原型,原型链就很好理解了。其实呢,就是在你访问对象实例的属性时,查找属性的一条链路。先上图:

当你从对象实例person上访问某个属性时,先查找自有属性,然后到函数原型Person.prototype上查找,最后再到函数原型Object.prototype上查找,如果还是找不到,就会返回undefined或者报错。

2、理解Function和Object的关系:

内容较多,且难以理解。我将再写篇文章进行详细介绍,敬请关注。

一文搞懂JS中Function和Object的关系-CSDN博客

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com