javascript高级程序设计--创建对象的那些事儿

news/2024/11/27 6:21:03/

了解完了对象,也了解了常用的创建对象的方式--构造函数式和字面量式,那么除此自外,还有哪些创建对象的方式呢?

工厂模式

说白了就是一个封装函数,在函数内部定义对象的细节,最后返回之

 function createObj(name,job,age){var obj = new Object();obj.name = name;obj.job = job;obj.age = age;obj.logAge = function(){console.log(this.age)//该函数执行的时候是在对象中执行的所以,this指向对象本身}return obj}console.log(createObj("张三","小白",23))//是一个对象;var person = createObj("李四","会计",23);//person保存了一个指针,指向新创建的对象;var person1 = person;//共同指向同一个对象console.log(person.logAge);//23console.log(person1);//还是一个对象

构造函数模式

a).由构造函数创建出来的是一个对象,
b).构造函数内部的this指向的是new 出来的实例对象;
c).实例.constructor是一个指针,指向实例的创建者--构造函数,默认调用的是prototype对象的constructors属性;

d).构造函数归根结底也是一个函数,只是调用方式不同,当然其作为函数,也是可以像普通函数那样的调用的,只不过结果就不一样啦;普通函数也是一样,也可被当作构造函数那样调用。
  function CreateObj(name, job, age){//  var hobby = "作诗";this.name = name;this.job = job;this.age = age ;this.logAge = function(){console.log(this.age)}}var person_new = new CreateObj("王五","财务",27);//person_new是一个对象;var person_new1 = new CreateObj("吴六", "饭店老板", 46);//person_new是一个对象;person_new.logAge();//27person_new1.logAge()//46;console.log(person_new.constructor)//构造函数本身;console.log(person_new1 instanceof Object)//因为毕竟person_new1也是一个对象嘛!//构造函数当作普通函数调用;CreateObj("李白","诗人",48);//this此时指向的是window,因为调用的时候是在全局环境中调用的;console.log(name)//李白

构造函数.prototype(原型模式):

每一个函数都有该属性,是一个指针,指向一个对象(原型对象),该对象包含由该构造函数创建的所有实例对象所共有的属性和方法;与此同时,该原型对象也包含着一个constructor属性(是一个指针,指向拥有该原型对象的构造函数)

1.实例.__proto__:在通过构造函数创建实例后,该实例有一个属性__proto__,是一个指针,指向该构造函数的原型对象。也就相当于,实例.__proto__ = 构造函数.prototype;

      function Plant(height,classify){this.height = height;this.class = classify;}Plant.prototype.name = "水稻";//将来所有的实例都将拥有属性name,值为“水稻”console.warn(Plant.prototype.constructor)//构造函数本身;Plant.prototype.constructor.prototype.loca = "河南·许昌"//console.warn(Plant.prototype.constructor)//构造函数本身;var plant_xiaomai = new Plant(137,"旱季作物");//构造函数的实例console.log(plant_xiaomai);//一个对象console.log(plant_xiaomai.name)//水稻console.log(plant_xiaomai.loca);//河南.许昌console.log(plant_xiaomai.__proto__)//原型对象
2.访问构造函数实例的属性的搜索顺序:

当为实例对象添加一个属性的时候,如果该属性名和原型对象中的属性名一样,那么该属性就会屏蔽原型对象中的对应属性,结果是会阻止我们 访问原型中的对应属性(但不会修改),因为在访问实例中的某属性的时候,首先会访问实例中的属性,如果有就停止搜寻,如果没有就往构造函数的的原型对象中寻找
2.1实例.hasOwnProperty(prop):就是用来检测属性prop是存在于实例中还是对应构造函数的原型对象中,当存在于实例中时返回true,毕竟顾名思义--就是看看实例中有没有属性prop嘛,
2.2 原型模式也是有缺点的,其最大的缺点就是实例对象的属性高度共享,因为prototype中的属性是所有构造函数实例所共有的。 因此当修改原型对象中的属性的时候,其它实例访问该属性的时候也会发生改变

//  访问实例中的属性的时候,其访问机制是,首先会在实例中的属性中寻找,如果找到了就停止寻找,如果找不到就在该实例的//构造函数的原型中寻找....function Xmw (name,sex,age){this.name = name;this.age = age;this.sex = sex;}Xmw.prototype.school = "陈杨寨杨村庙小学";var dmw = new Xmw ("董曼文","女",7);//一个对象console.log(dmw.school);//陈杨寨杨村庙小学console.log(dmw.__proto__);//指向构造函数的原型对象console.log(dmw.__proto__ == Xmw.prototype);//truevar dhl = new Xmw("董涵琳","女",7);dhl.school = "吴刘小学"console.log(dhl.school)//吴刘小学;console.log(dhl.hasOwnProperty("school"));//truedelete dhl.school;//删除实例属性console.log(dhl.school)//杨村庙小学,没有了同名的实例属性,就会寻找该实例的对应构造函数的原型中的属性
构造函数和原型的正确打开方式

1.构造函数+prototype混用(推荐):创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式。构造函数(可传参)模式用于定义实
 例属性,而原型模式用于定义方法和共享的属性。

function Animal(name,age,weight){this.name = name;this.age = age;this.weight = weight;this.height = 1.03;}Animal.prototype = {constructor:Animal,//显式指定constructor指针的指向sayAniName:function(){console.log(this.name)}}var cat = new Animal("傲娇Cat",1,5);//一个对象console.log(cat);cat.sayAniName()//傲娇Catcat.height =1.30console.log(cat.height)//1.30var dog = new Animal("憨厚Dog",2,20);//另一个对象console.log(dog.height)//1.03,因为dog实例对象中的height属性是1.03
2. 动态原型模式(不推荐)

           function Animal_1(name, age, weight){this.name = name;this.age = age;this.weight = weight;this.height = 1.03;if(typeof this.sayAniName != "function"){//当实例中没有sayAniName属性的时候,//这段代码只会在初次调用构造函数时才会执行。此后,原型已经完成初始化Animal_1.prototype.sayAniName = function(){console.log(this.name)}}}var cat1 = new Animal_1("粘人猫",2,9);//新创建的实例,此时就会执行if语句,因为此时满足跳捡,在此之后,当再次调用该构造函数的时候不执行if语句了//,因为此时实例已经有了公用的方法了cat1.sayAniName()//粘人猫var dog1 = new Animal_1("淘气狗",2,10);dog1.sayAniName()//淘气狗
3.寄生构造函数模式(不推荐):说白就是一个构造函数,在函数体内新建一个对象,然后定义对象的一些细节,最后返回对象 然后调用的时候使用 new 操作符
 function Plant(classify,iswatered){var plant = new Object();plant.classify = classify;plant.iswatered = iswatered;return plant}var apple = new Plant("灌木类",false);//既可以被当作构造函数使用var orange = Plant("草",true);//也可也被当作普通的函数使用console.log(apple);console.log(orange);
4.稳妥构造函数模式(一般用在安全性要求高的环境中) 和寄生构造函数模式差不多, 只不过在该模式下,新创建对象的实例方法不引用this(也就是说,在构造函数中定义对象实例细节的时不能使用this),其二不使用new操作符调用构造函数(要像调用普通函数那样调用)

function Person(name, age, weight) {var person = new Object();person.alertName = function () {alert(name)}return person}//新对象Person("张三", 23, 170).alertName();//张三

注意:

        函数对象有 __proto__ 属性,又有 prototype 属性。普通对象只有 __proto__ 属性,没有 prototype 属性。

console.log(obj.__proto__)//Object对象console.log(obj.prototype)//undefinedfunction abs(){console.log(1)}console.log(abs.__proto__)//function对象的原型console.log(abs.prototype)//将abs其视为一个对象,对象的原型是Object

  1. Function.prototype 比较特殊,是个空函数,因为Function是一个构造函数,构造函数.prototype指向该构造函数的原型对象

  2. typeof Function.prototype 输出 “function” 但是它不能当成构造器,Function.prototype.prototype 为 undefined

  3. Object.prototype.__proto__ 为 null,原型链到这里结束。

更多信息请参考:JavaScirpt深入之从原型到原型链



http://www.ppmy.cn/news/878438.html

相关文章

史上最易懂的红黑树动态图解!

点击蓝色“程序猿DD”关注我 回复“资源”获取独家整理的学习资料! 本文转载自公众号:日拱一兵 红黑树,对很多童鞋来说,是既熟悉又陌生。学校中学过,只了解大概;工作中不怎么使用,但面试又是重点…

2021蓝桥杯初中组6月比赛试题

蓝桥杯初中python试题 编程题自我评价题目 1题目 2题目 3题目 4题目 5题目 6 编程题 作者:Jeefy,xsh_Fu 邮箱:jeefy163163.com / jeefyoloutlook.com github: jeefiesgithub.com 源代码都在文章之中,仅供参考 自我评价 对于我这个…

自学是门手艺

自学是门手艺 One has no future if one couldnt teach themself. 作者:李笑来 特别感谢霍炬(virushuo)、洪强宁(hongqn) 两位良师诤友在此书写作过程中给予我的巨大帮助! 关于作者 李笑来,投资人&#…

Android 淘气三千传之 —— 插件化的一点理解(上)

插件化 这一篇主要是个人对插件化涉及到的一些基础知识的理解,内容都比较简单: 包括以下内容: 目录: 1、类加载机制 2、Binder机制 3、APP、四大组件的启动流程 4、APK安装过程 5、资源的加载过程 6、Hook机制 7、OOP 8、面向切面编程 9、代理模式 10、插件化…

shell 匹配字符串 (eg.获得配置文件的值 )

第一种: source/data/deploy/draco/env.properties SERVER_ID$SERVERID 第二种: cat /data/deploy/draco/env.properties |grep SERVERID|grep -E -o "[0-9]" 第三种: cat /data/deploy/draco/env.properties |grep SERVERID|awk -…

JavaScript------JS相关难题,做对一半算你牛牪犇

1. parseInt 遇上 map [1,2,3].map(parseInt)// A. ["1", "2", "3"] // B. [1, 2, 3] // C. [0, 1, 2] // D. [1, NaN, NaN]答案是D。实际上返回的结果是 [1, NaN, NaN] , 因为 parseInt 函数只需要两个参数 parseInt(value, radix)…

饥荒服务器怎么显示帧数,饥荒的fps值怎么显示 | 手游网游页游攻略大全

发布时间:2016-06-17 淘气值与坎普斯大家知道吗?今天笔者就为大家带来了饥荒淘气值(顽皮值)与坎普斯打法图文详解,非常不错的内容哦,小伙伴们你们知道这些吗?下面赶快跟我一起来看看吧. 淘气值(顽皮值) 淘气值,饥荒中的一项隐 ... 标签: 攻略 饥荒 生存技巧 BOSS怪物 发布时…

【无标题】 2022淘宝天猫双十一喵果总动员玩法攻略

天猫双11全球狂欢节,双11喵果总动员活动规则! 超级红包领取方法1:打开手机淘宝搜索:能省就省50,即可领取1111超级红包 一、活动时间 整体活动时间为 2022年10月25日00:00:00—2022年11月11日21:59:59,其…