博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript中创建对象的5种模式
阅读量:7294 次
发布时间:2019-06-30

本文共 4617 字,大约阅读时间需要 15 分钟。

构造函数模式

实现方式:
function Person(name, age, job) {    this.name = name;    this.age = age;    this.job = job;    this.sayName = function() {        return this.name    }}// 测试var person = new Person('Nicholas', 29, 'Engineer');// 检测对象类型console.log(person.constructor === Person);  // trueconsole.log(person instanceof Person);  // trueconsole.log(Person instanceof Object);  // true
注意:
  • 构造函数名使用首字母大写。
  • 使用new操作符创建实例。
  • 优点:
    • 可以使用instanceof操作符检测对象类型。
  • 缺点:
    • 每个方法都要在每个实例上重新创建一遍。不同实例的同名函数不相等。
var person1 = new Person('Nicholas', 29, 'Engineer');var person2 = new Person('Greg', 30, 'Doctor');console.log(person1.sayName === person2.sayName);  // false

原型模式

实现方式:
function Person() {}Person.prototype.name = "Nicholas";Person.prototype.age = 29;Person.prototype.job = "Engineer";Person.prototype.sayName = function() {    return this.name;}// 测试var person = new Person();console.log(person.sayName());  // Nicholas// 检测对象类型console.log(person.constructor === Person);  // trueconsole.log(person instanceof Person);  // trueconsole.log(Person instanceof Object);  // true
原型链:

1034314-20170426101743537-1068642196.jpg

关于原型:
  • 构造函数与原型对象
    • 构造函数获得一个prototype属性,指向函数的原型。
    • 原型获得一个constructor属性,指向构造函数。
  • 实例对象与原型对象
    • 创建实例后,实例获得内部属性[[Prototype]]_proto_,指向构造函数的原型。
    • isPrototypeOf()方法会返回一个布尔值,可以确定实例和原型的关系。
    • Object.getPrototypeOf()方法会返回实例对应的原型。
// isPrototypeOf()方法console.log(Person.prototype.isPrototypeOf(person));  // true// Object.getPrototypeOf()方法console.log(Object.getPrototypeOf(person) === Person.prototype); // true
  • 访问原型链
    • 读取实例的属性:如果在实例中找到了该属性,则返回属性的值;如果没有找到,则继续搜索原型的同名属性,如果找到则返回该属性。
    • 添加实例的属性:如果在实例中添加一个属性,而该属性与原型中的一个属性同名。则在实例中创建该属性,并屏蔽原型中的同名属性。
    • 删除实例的属性:如果删除了实例的属性,则会使原型中的同名属性暴露出来。
// 添加属性person.name = "Greg";console.log(person.name);  // Greg// 删除属性delete person.name;console.log(person.name);  // Nicholas
  • 使用对象字面量定义原型
    • 需要手动设置原型的constructor属性
    • 默认的construnctor属性是不可枚举的。可以使用Object.defineProperty()方法定义。
function Person() {};Person.prototype = {    // constructor: Person,    name: 'Nicholas',    age: 29,    job: 'Engineer',    sayName: function() {        return this.name;    }};Object.defineProperty(Person.prototype, 'constructor', {    enumerable: false,    value: Person});// 测试var person = new Person();console.log(person.sayName());  // Nicholas// 检测对象类型console.log(person.constructor === Person);  // trueconsole.log(person instanceof Person);  // trueconsole.log(Person instanceof Object);  // true
注意:
  • 使用new操作符创建实例。
  • 优点:
    • 可以使用instanceof操作符检测对象类型。
    • 所有对象实例共享原型对象所包含的属性和方法。
  • 缺点:
    • 对于引用类型值,会存在实例意外修改原型的风险。
function Student() {}Student.prototype.friends = ['Shelby', 'Court'];// 测试var stu1 = new Student();var stu2 = new Student();stu1.friends.push('Van');   // 实例stu1修改了原型的friends属性,并影响到了stu2console.log(stu1.friends);  // ["Shelby", "Court", "Van"] console.log(stu2.friends);  // ["Shelby", "Court", "Van"]

组合模式:构造函数模式&原型模式

实现方式:
function Person(name, age, job) {    this.name = name;    this.age = age;    this.job = job;}Person.prototype.sayName = function() {    return this.name;}// 测试var person = new Person('Nicholas', 29, 'Engineer');console.log(person.sayName());  // Nicholas// 检测对象类型console.log(person.constructor === Person);  // trueconsole.log(person instanceof Person);  // trueconsole.log(Person instanceof Object);  // true
注意:
  • 使用new操作符创建实例。
  • 构造函数用于自定义实例属性,原型中定义方法和共享属性。
  • 优点:
    • 可以使用instanceof操作符检测对象类型。
    • 每个实例都会有自己的一份实例属性的副本,同时又共享着对方法的引用,最大限度地节省了内存。
    • 支持向构造函数传递参数。

动态原型模式

实现方式:
function Person(name, age, job) {    // 属性    this.name = name;    this.age = age;    this.job = job;        // 方法    if (typeof this.sayName !== 'function') {        Person.prototype.sayName = function() {            return this.name;        }    }}// 测试var person = new Person('Nicholas', 29, 'Engineer');console.log(person.sayName());  // Nicholas// 检测对象类型console.log(person.constructor === Person);  // trueconsole.log(person instanceof Person);  // trueconsole.log(Person instanceof Object);  // true
注意:
  • 使用new操作符创建实例。
  • 原型初始化只在初次调用构造函数时才执行。
  • 不能使用对象字面量方式重写原型。否则就会切断现有实例与新原型之间的关系。
  • 优点:
    • 可以使用instanceof操作符检测对象类型。
    • 把所有信息都封装在构造函数中,在构造函数中初始化原型,保持了同时使用构造函数和原型的优点。

寄生构造函数模式

实现方式:
function Person(name, age, job) {    var o = new Object();    o.name = name;    o.age = age;    o.job = job    o.sayName = function() {        return o.name;    }    return o;}// 测试var person = new Person('Nicholas', 29, 'Engineer');console.log(person.sayName());  // Nicholas// 检测对象类型console.log(person.constructor === Person);  // falseconsole.log(person instanceof Person);  // falseconsole.log(Person instanceof Object);  // true
注意:
  • 可以不使用new操作符创建实例。在不使用new操作符时,又被称为工厂模式
  • 在构造函数末尾添加return语句,可以重写调用构造函数时的返回值。
  • 无法使用instanceof操作符检测对象类型。因为返回的对象与构造函数及原型之间没有关系。

参考:《JavaScript高级程序设计》

转载于:https://www.cnblogs.com/gymmer/p/6767243.html

你可能感兴趣的文章
OCP读书笔记(5) - 使用RMAN创建备份
查看>>
java的接口和抽象类区别
查看>>
能够提高PHP的性能的一些注意事项
查看>>
020-请你说一说app测试的工具
查看>>
软件测试2019:第五次作业—— 安全测试(含安全测试工具实验)
查看>>
SSM框架搭建总结(2)
查看>>
Python学习(19)正则表达式
查看>>
PHP中空字符串、0、null、empty和false之间的关系
查看>>
【深度学习篇】---CNN和RNN结合与对比,实例讲解
查看>>
201771010126 王燕《面向对象程序设计(Java)》第十二周学习总结
查看>>
XAML实例教程系列 - 资源(Resources)
查看>>
LWIP互联网资料汇总
查看>>
外贸术语
查看>>
网络传输流量控制策略小结
查看>>
上传大文件
查看>>
Mybatis面试集合(转)
查看>>
分布式系统的完整介绍(一)
查看>>
考点1
查看>>
Asp.net 程序连接orcle如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,...
查看>>
自己写的模板引擎,模板生成静态页面
查看>>