秒懂JS创建对象的方式
发布日期:2022-02-22 16:04:46
浏览次数:32
分类:技术文章
本文共 4306 字,大约阅读时间需要 14 分钟。
一、创建单个对象实例
- 构造函数创建对象:var obj=new Object(); obj.属性名=属性值; 添加属性
- 对象字面量 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, '软件工程师');
- 问题:不能做到函数复用
三、构造函数模式
- 构造函数首字母大写
- 使用new 创建对象,没有显式创建对象
- 构造函数的作用域赋值给新对象,this指向这个新对象,直接将属性和方法赋值给this
- 构造函数中,不写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 操作符调用构造函数创建实例的过程
- 创建一个新对象
- 将构造函数作用域赋值给新对象,this指向新对象
- 执行构造函数中的代码,为新对象添加属性
- 返回新对象 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
-
原型和实例的关系:
- 原型.isPrototypeOf(实例)方法判断对象之间是否存在原型关系,存在 返回true
- Object.getPrototypeOf(实例); 返回对象的原型。支持IE9+
原型链:当代码读取某个对象的属性时,从实例本身构造函数开始查找,如果没有找到,查找__proto__ 指向的原型对象。
自身属性和原型属性
- 优先访问自身属性
- 使用null清空自身属性,再次访问该属性时不能访问到原型上的同名属性。
- 用delete删除自身属性,delete person.name; 会获取到原型属性。
区分自身属性和原型属性
- 实例.hasOwnProperty(‘属性’) 方法继承于Object
- 检测一个属性存在于实例中还是原型中,在实例中,返回true
- ‘属性’ 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
第一次来,支持一个
[***.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
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全栈开发---Java ERP系统开发:商业ERP(九)销售订单
2019-04-26
Java全栈开发---Java ERP系统开发:商业ERP(十)销售统计
2019-04-26