javascript创建对象 之 原型模式的理解

本文围绕JavaScript原型对象展开,介绍了原型概念及用途,阐述了构造函数、原型、实例三者关系,如通过多种方法判断属性位置。还提及更简单的原型语法、原型的动态性、原生对象的原型,同时指出原型对象存在共享属性值的问题,不建议单独使用原型模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 原型概念:每个函数都有一个 prototype (原型)属性,这个属性是一个指针,指向一个对象。
  • 用途:让所有对象实例共享它所包含的属性和方法。

代码示例:

function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
  alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true

1.理解原型对象

  • 只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype 属性,这个属性指向函数的原型对象
  • 在默认情况下,所有原型对象都会自动获得一个 constructor(构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针。

2.构造函数、原型、实例三者关系

 

Person.prototype.constructor == Person

【1】isPrototypeOf() 判断原型对象是否是实例的原型

Person.prototype.isPrototypeOf(person1) // true

【2】Object.getPrototypeOf() 获取实例的原型

Object.getPrototypeOf(person1)
//浏览器支持:IE9+、Firefox 3.5+、Safari 5+、Opera 12+ 和 Chrome。

【3】多个实例可以共享原型的属性和方法

读取某个对象的某个属性时,先从对象实例本身开始,找到了则返回;没找到则继续搜索原型对象。

【4】hasOwnProperty() 检测一个属性是否存在于实例本身中(不在原型上)

person1.hasOwnProperty("name")

【5】key in object 

单独使用in 操作符,会在通过对象能够访问给定属性时返回 true,无论该属性存在于实例中还是原型中。

判断属性是原型中的属性(不在实例上):

function hasPrototypeProperty(object, name){
  return !object.hasOwnProperty(name) && (name in object);
}

【6】for (var key in object) { } 

使用 for-in 循环时,返回的是所有能够通过对象访问的、可枚举的属性,其中既包括存在于实例中的属性,也包括存在于原型中的属性。

【7】不可枚举属性:hasOwnProperty()、propertyIsEnumerable()、toLocaleString()、toString()、valueOf();constructor 和 prototype

【8】Object.keys(对象)   获取对象上所有可枚举的实例属性,返回一个包含所有可枚举属性的字符串数组

 var keys = Object.keys(obj);

【9】Object.getOwnPropertyNames()   获取所有实例属性(无论是否可枚举)

var keys = Object.getOwnPropertyNames(Person.prototype) 
// ['constructor','name','age','job','sayName']

3.更简单的原型语法

用一个包含所有属性和方法对象字面量来重写整个原型对象。

  • 出现问题: 原型对象上的 constructor 属性不再指向预想中的构造函数(Person),指向 Object 构造函数
  • 解决方法(如需要):手动设置 constructor : Person
function Person(){
}

Person.prototype = {
  constructor : Person,  // 导致[[Enumerable]]特性被设置为true
  name : "Nicholas",
  age : 29,
  job: "Software Engineer",
  sayName : function () {
    alert(this.name);
  }
};


//兼容 ECMAScript 5 的 JavaScript 引擎可以使用 Object.defineProperty():

Object.defineProperty(Person.prototype, "constructor", {
  enumerable: false,
  value: Person
});

4.原型的动态性

【1】实例与原型之间的松散连接关系

可以随时为原型添加属性和方法,修改能够立即从实例上反映出来。

5.原生对象的原型

所有原生引用类型(Object、Array、String,等等)都在其构造函数的原型上定义了方法,如 Array.prototype 的 sort() 方法。

可以修改原生对象的原型,可以随时添加方法。
不推荐修改原生对象的原型

6.原型对象的问题

  1. 所有实例在默认情况下都将取得相同的属性值
  2. 最大问题是由其共享的本性所导致:函数共享很合适,基本值属性也没问题,但对于包含引用类型值的属性问题比较突出

例如:原型属性有一个是数组,给一个实例的数组添加一项,所有数组都变了====> 不单独使用原型模式 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值