秒懂JS创建对象的方式
发布日期:2022-02-22 16:04:46 浏览次数:32 分类:技术文章

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

一、创建单个对象实例

  1. 构造函数创建对象:var obj=new Object(); obj.属性名=属性值; 添加属性
  2. 对象字面量 obj{属性名:属性值,…}
  • 问题:使用一个接口创建很多对象,产生大量重复代码
  • 解决:工厂模式

二、工厂模式

  • 用函数封装接口创建对象的细节,调用函数创建多个对象。
function createPerson(name, age, job) {
var obj = new Object(); obj.name = name; obj.age = age; obj.job = job; obj.sayname = function() {
console.log(this.name); } return obj; //创建一个新对象,将对象返回 } var obj1 = createPerson('张三', 20, '软件工程师'); var obj2 = createPerson('李四', 22, '软件工程师');
  • 问题:不能做到函数复用

三、构造函数模式

  • 构造函数首字母大写
  1. 使用new 创建对象,没有显式创建对象
  2. 构造函数的作用域赋值给新对象,this指向这个新对象,直接将属性和方法赋值给this
  3. 构造函数中,不写return语句 或 return 基本类型; 会将this作为返回值。 return对象; 会将对象作为返回值
function Person(name, age, job) {
this.name = name; this.age = age; this.job = job; this.sayname = function() {
console.log(this.name); } } var obj3 = new Person('张三', 20, '软件工程师'); var obj4 = new Person('李四', 22, '软件工程师'); console.log(obj3.sayname==obj4.sayname);//false

使用new 操作符调用构造函数创建实例的过程

  1. 创建一个新对象
  2. 将构造函数作用域赋值给新对象,this指向新对象
  3. 执行构造函数中的代码,为新对象添加属性
  4. 返回新对象 return this;

构造函数作为普通函数 直接调用是给window添加属性和方法

构造函数模式的缺点

  • 每个方法都要在每个实例上重新创建一遍。因为方法(函数)是对象,每定义一个方法,就是实例化了一个对象。
  • 解决:原型模式

四、原型模式

  • 每个函数都有原型属性prototype ,是一个指针,指向函数的原型对象
  • 原型对象,可以让所有对象实例共享所有它所包含的属性和方法。
  • 原型模式创建对象: 在原型上添加属性和方法 Person.prototype.属性名=‘属性值’
function Person() {
//构造函数 } // 在原型上添加属性和方法 Person.prototype.name = '张三'; Person.prototype.age = '21'; Person.prototype.job = '前端攻城狮' Person.prototype.sayName = function() {
console.log(this.name); } //必须先重写原型再创建实例对象 var person1=new Person(); var person2=new Person(); console.log(person1.sayName==person2.sayName);//true 引用同一个方法

原型、构造函数 、实例的关系

  • 实例对象的constructor属性指向构造函数。person.constructor == Person

  • 构造函数原型对象的constructor属性指向该构造函数。Person.prototype.constructor==Person

  • 构造函数的prototype属性指向构造函数的原型对象(简称原型)

  • 构造函数与原型之间类似双向链表的关系

  • 实例对象的__proto__ 属性直接指向构造函数的原型对象。兼容性:safari,firefox,chrome可以使用

    person.__proto__==Person.prototype

  • 构造函数和实例的关系: 实例 instanceof 原型链中的构造函数 返回true

  • 原型和实例的关系:

    1. 原型.isPrototypeOf(实例)方法判断对象之间是否存在原型关系,存在 返回true
    2. Object.getPrototypeOf(实例); 返回对象的原型。支持IE9+

原型链:当代码读取某个对象的属性时,从实例本身构造函数开始查找,如果没有找到,查找__proto__ 指向的原型对象。

自身属性和原型属性

  • 优先访问自身属性
  • 使用null清空自身属性,再次访问该属性时不能访问到原型上的同名属性。
  • 用delete删除自身属性,delete person.name; 会获取到原型属性。

区分自身属性和原型属性

  1. 实例.hasOwnProperty(‘属性’) 方法继承于Object
    • 检测一个属性存在于实例中还是原型中,在实例中,返回true
  2. ‘属性’ in 实例; in操作符 可以通过对象访问到给定属性时(无论是实例中还是原型中)返回true。

原型模式 使用对象字面量添加原型属性 的问题

问题一:使用单独的Person.prototype 添加属性时,会保留原型中自带的constructor属性。

使用对象字面量添加属性时 会重写原型对象 ,失去默认的constructor属性。原型指向新的内存空间。

  • 解决: 在原型里 手动添加 constructor属性 指向构造函数

问题二:先创建实例对象,再使用对象字面量添加原型属性时,不能使用原型中的属性和方法。

  • 原型指向新的地址,构造函数可以自动指向新的地址,而实例仍然指向旧的原型地址.
  • 解决:创建对象写在原型下面。

原型模式 自身的问题

  • 使用实例对象可以修改 原型中引用类型的属性,而这个属性被所有实例共享

五、组合使用构造函数 和 原型模式 —— 创建自定义类型的常见方式

  • 构造函数定义实例属性
  • 原型上定义方法和共享的属性
//属性写在构造函数里面,每个对象都有自己的属性		function Person(name, age, job){
this.name = name; this.age = age; this.job = job; this.friends=['lily','nacy'];//引用类型的属性值 } Person.prototype={
constructor:Person, //方法写在原型里,实例可以共享 sayName:function(){
console.log(this.name); } } var person1=new Person('张三',29,'软件工程师'); var person2=new Person('李四',39,'医生'); person1.friends.push('tom'); //引用类型的属性值 不共享 console.log(person1.friends);//(3) ["lily", "nacy", "tom"] console.log(person2.friends);//(2) ["lily", "nacy"] console.log(person1.sayName==person2.sayName);//true 指向同一个地址

六、动态原型模式

  • 将独立的构造函数和原型封装在构造函数中,仅在必要时初始化原型
  • 不能使用对象字面量重写原型
function Person(name, age, job){
this.name = name; this.age = age; this.job = job; if(typeof this.sayName != 'function'){
Person.prototype.sayName=function(){
console.log(this.name); } } } var obj1=new Person('lily',25,'后勤'); var obj2=new Person('nacy',25,'财务'); obj1.sayName();//lily obj2.sayName(); console.log(obj1.sayName== obj2.sayName)//true 共享原型方法

七、寄生构造函数模式

  • 类似于 工厂模式+构造函数模式
function Person(name, age, job){
var o=new Object(); o.name=name; o.age = age; o.job = job; o.sayName=function(){
console.log(this.name); } return o; } var obj=new Person('lily',25,'后勤'); obj.sayName();//lily

八、稳妥构造函数模式

  • 稳妥对象指没有公共属性,方法也不引用this的对象。适合在安全环境中使用
function Person(name, age, job){
var o=new Object(); // 可以定义私有变量和函数 var name='lily'; function otherFunc(){
conosle.log('ok'); } o.sayName=function(){
console.log(name); } return o; } var obj=new Person3('lily',25,'后勤'); obj.sayName();//lily

转载地址:https://blog.csdn.net/Conradine_Lian/article/details/105278930 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:深入探究JS基本数据类型及其转换
下一篇:DOM文档对象模型(思维导图版)

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年04月08日 08时04分25秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

Exception Report node to traverse cannot be null! The server encountered an unexpected condition 2019-04-26
联系人管理-客户拜访记录| CRM客户关系管理系统项目 实战七(Struts2+Spring+Hibernate)解析+源代码 2019-04-26
联系人管理-权限拦截器| CRM客户关系管理系统项目 实战八(Struts2+Spring+Hibernate)解析+源代码 2019-04-26
SSH注解整合项目(struts2+Spring+Hibernate)客户关系管理系统 2019-04-26
Java Web当中使用EasyUI|快速建立漂亮的后台网站(教程+源代码) 2019-04-26
Oracle快速入门(基本概念+查询大全) 2019-04-26
Oracle使用PLSQL查询的时候中文乱码问题的解决 2019-04-26
Oracle快速入门(常用函数大全) 2019-04-26
Oracle快速入门(多表查询大全) 2019-04-26
计算机二级C语言重要考点知识总结 2019-04-26
Oracle快速入门(PLSQL编程) 2019-04-26
Java全栈开发---Java ERP系统开发:商业ERP(三)部门管理(增删改查) 2019-04-26
Java全栈开发---Java ERP系统开发:商业ERP(四)通用工具类的抽取 2019-04-26
Java全栈开发---Java ERP系统开发:商业ERP(五)员工管理的完善 2019-04-26
Java全栈开发---Java ERP系统开发:商业ERP(六)商品功能的完善 2019-04-26
Java全栈开发---Java ERP系统开发:商业ERP(七)登录与密码管理 2019-04-26
Java全栈开发---Java ERP系统开发:商业ERP(八)采购申请 2019-04-26
Java多线程(案例+解析)基本概念:程序、进程、线程、使用多线程,Thread当中有关的方法,线程的调度,解决线程安全问题 2019-04-26
Java全栈开发---Java ERP系统开发:商业ERP(九)销售订单 2019-04-26
Java全栈开发---Java ERP系统开发:商业ERP(十)销售统计 2019-04-26