一、理解对象

1.创建一个对象,然后给这个对象新建属性和方法。
①常见的创建方式

var person = new Object(); //创建一个Object 对象person.name = 'XIE'; //创建一个name 属性并赋值person.age = 20; //创建一个age 属性并赋值person.sayName = function () { //创建一个run()方法并返回值return this.name; //this指的是person本身};

②字面量的形式

var person = {name:"xie",age:20,job:"学生",sayName:function(){return this.name;}
}

2.数据属性
数据属性有4个描述其行为的特性。

特性 默认值 含义
configurable true 是否可配置,表示能否删除属性重新定义,能否修改属性的特性,能否修改为访问器属性。
enumerable true 是否可枚举
writable true 是否可修改属性值
value undefined 属性的数据值

注:configurable特性一旦设置为false后,则不能再变为true.

var person={};
Object.defineProperty(person,"name",{configurable:true,enumerable:true,writable:true,value:"xie"
})

3.访问器属性

特性 默认值 含义
configurable true 是否可配置,表示能否删除属性重新定义,能否修改属性的特性,能否修改为访问器属性。
enumerable true 是否可枚举
get undefined 读取属性时调用
set undefined 写入属性时调用

二、创建对象

1.工厂模式

function createObject(name, age) { //集中实例化的函数var obj = new Object();obj.name = name;obj.age = age;obj.run = function () {return this.name + this.age + '运行中...';};return obj;
}
var box1 = createObject('Lee', 100); //第一个实例
var box2 = createObject('Jack', 200); //第二个实例

工厂模式解决了重复实例化的问题,但还有一个问题,那就是识别问题,因为根本无法弄清楚一个对象的类型。

2.构造函数模式

function Person(name,age){this.name = name;this.age = age;this.run = function(){alert(this.name);}
}
var person1 = new Person("Lee",100);
var person2 = new Person("Jack",200);

使用了构造函数的方法,和使用工厂模式的方法他们不同之处如下:

  1. 构造函数方法没有显示的创建对象(new Object());
  2. 直接将属性和方法赋值给this 对象;
  3. 没有renturn 语句。

构造函数的方法有一些规范:

  • .函数名和实例化构造名相同且大写,(PS:非强制,但这么写有助于区分构造函数和普通函数);
  • 通过构造函数创建对象,必须使用new 运算符。

使用new操作符创建实例时,执行过程如下:

  1. 创建一个新对象;
  2. 将构造函数的作用域赋给新对象(因此this就指向了这个对象);
  3. 执行构造函数中的代码(为这个新对象添加属性);
  4. 返回新对象

    使用构造函数的主要问题,就是每个方法都要再每个实例上重新创建一遍。通过下面可知不一样:

alert(person1.run == person2.run);  //false

3.原型模式

我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法。使用原型的好处可以让所有对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息添加到原型中。

3.1常见的语法

// 原型模式
function Box() {} //声明一个构造函数
Box.prototype.name = 'Lee'; //在原型里添加属性
Box.prototype.age = 100;
Box.prototype.run = function () { //在原型里添加方法return this.name + this.age + '运行中...';
};
//比较一下原型内的方法地址是否一致:
var box1 = new Box();
var box2 = new Box();
alert(box1.run == box2.run); //true,方法的引用地址保持一致
为

下面可通过图进一步了解


在原型模式声明中,多了两个属性,这两个属性都是创建对象时自动生成的。proto属性是实例指向原型对象的一个指针,ECMAScript5称这个指针为[[Prototype]],它的作用就是指向构造函数的原型属性constructor。

isPrototypeOf()方法来判断一个对象是否指向了该构造函数的原型

alert(Box.prototype.isPrototypeOf(box1)); //true,只要实例化对象,即都会指向

Object.getPrototype()方法返回[[Prototype]]的值。IE9+,Firefox3.5+,Safari5+,Opera12+ 和Chrome支持

alert(Object.getPrototype(box1).name);  //Lee

原型模式的执行流程:

  1. .先查找构造函数实例里的属性或方法,如果有,立刻返回;
  2. 如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回;

hasOwnProperty()函数判断构造函数的实例中是否有该属性。

alert(box.hasOwnProperty('name')); //实例里有返回true,否则返回false

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

alert('name' in box); //true,存在实例中或原型中
function isProperty(object, property) { //判断原型中是否存在属性return !object.hasOwnProperty(property) && (property in object);
}

3.2更简单的原型语法

为了让属性和方法更好的体现封装的效果,并且减少不必要的输入,原型的创建可以使用字面量的方式:

function Box() {};
Box.prototype = { //使用字面量的方式name : 'Lee',age : 100,run : function () {return this.name + this.age + '运行中...';}
};

使用构造函数创建原型对象和使用字面量创建对象在使用上基本相同,但还是有一些区别,字面量创建的方式使用constructor 属性不会指向实例,而会指向Object,构造函数创建的方式则相反。

var box = new Box();
alert(box instanceof Box);  //true
alert(box instanceof Object);  //true
alert(box.constructor == Box); //字面量方式,返回false,否则,true
alert(box.constructor == Object); //字面量方式,返回true,否则,false

如果想让字面量方式的constructor 指向实例对象,可以如下所示

function Box() {};
Box.prototype = { //使用字面量的方式constructor : Box, //直接强制指向即可name : 'Lee',age : 100,run : function () {return this.name + this.age + '运行中...';}
};

重设constructor会导致它的enumerable特性被修改为true,默认情况下,原生的constructor是不可枚举的,可使用Object.defineProperty()方法重设构造函数。

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

原型的声明是有先后顺序的,所以,重写的原型会切断之前的原型。

function Box() {};
Box.prototype = { //原型被重写了constructor : Box,name : 'Lee',age : 100,run : function () {return this.name + this.age + '运行中...';}
};
Box.prototype = {age = 200
};
var box = new Box(); //在这里声明
alert(box.run()); //erroe,因为box 只是最初声明的原型

3.3原型对象的问题

原型模式创建对象也有自己的缺点,它省略了构造函数传参初始化这一过程,带来的缺点就是初始化的值都是一致的。而原型最大的缺点就是它最大的优点,那就是共享。原型中所有属性是被很多实例共享的,共享对于函数非常合适,对于包含基本值的属性也还可以。但如果属性包含引用类型,就存在一定的问题:

function Box() {};
Box.prototype = {constructor : Box,name : 'Lee',age : 100,family : ['父亲', '母亲', '妹妹'], //添加了一个数组属性run : function () {return this.name + this.age + this.family;}
};
var box1 = new Box();
box1.family.push('哥哥'); //在实例中添加'哥哥'
alert(box1.run());
var box2 = new Box();
alert(box2.run()); //共享带来的麻烦,也有'哥哥'了

4.动态原型模式

为了解决构造传参和共享问题,可以组合构造函数+原型模式,即动态原型模式。

function Box(name ,age) { //将所有信息封装到函数体内this.name = name;   //不共享的使用构造函数形式this.age = age;if (typeof this.run != 'function') { //仅在第一次调用的初始化Box.prototype.run = function () {   //共享的使用原型模式return this.name + this.age + '运行中...';};}
}
var box = new Box('Lee', 100);
alert(box.run());

当第一次调用构造函数时,run()方法发现不存在,然后初始化原型。当第二次调用,就不会初始化,并且第二次创建新对象,原型也不会再初始化了。这样及得到了封装,又实现了原型方法共享,并且属性都保持独立。
PS:使用动态原型模式,要注意一点,不可以再使用字面量的方式重写原型,因为会切断实例和新原型之间的联系。

5.寄生构造函数模式

寄生构造函数,其实就是工厂模式+构造函数模式。这种模式比较通用,但不能确定对象关系。

function myString(string) {var str = new String(string);str.addstring = function () {return this + ',被添加了!';};return str;
}
var box = new myString('Lee'); //比直接在引用原型添加要繁琐好多
alert(box.addstring());

使用场景:要创建一个具有额外方法的引用类型时。

6.稳妥构造函数模式

在一些安全的环境中,比如禁止使用this 和new,这里的this 是构造函数里不使用this,这里的new 是在外部实例化构造函数时不使用new。

function Box(name , age) {var obj = new Object();obj.run = function () {return name + age + '运行中...'; //直接打印参数即可};return obj;
}
var box = Box('Lee', 100); //直接调用函数
alert(box.run());

PS:稳妥构造函数和寄生类似。

JavaScript 面向对象的程序设计1相关推荐

  1. javascript:面向对象的程序设计

    一:理解对象属性 对象有两种属性:数据属性和访问器属性. 1)数据属性 数据属性有四个描述其行为的特性,[[configurable]] [[enumerable]] [[writable]] [[v ...

  2. javascript高级程序设计第3版——第6章 面向对象的程序设计

    第六章--面向对象的程序设计 这一章主要讲述了:面向对象的语言由于没有类/接口情况下工作的几种模式以及面向对象语言的继承: 模式:工厂模式,构造函数模式,原型模式 继承:原型式继承,寄生式继承,以及寄 ...

  3. 《JavaScript面向对象精要》读书笔记

    JavaScript(ES5)的面向对象精要 标签: JavaScript 面向对象 读书笔记 2016年1月16日-17日两天看完了<JavaScript面向对象精要>(参加异步社区的活 ...

  4. javascript面向对象系列第一篇——构造函数和原型对象

    前面的话 一般地,javascript使用构造函数和原型对象来进行面向对象编程,它们的表现与其他面向对象编程语言中的类相似又不同.本文将详细介绍如何用构造函数和原型对象来创建对象 构造函数 构造函数是 ...

  5. 《JavaScript面向对象编程指南》——第1章 引言1.1 回顾历史

    本节书摘来自异步社区<JavaScript面向对象编程指南>一书中的第1章,第1.1节,作者: [加]Stoyan Stefanov 译者: 凌杰 更多章节内容可以访问云栖社区" ...

  6. 面向对象的程序设计——理解对象

    面向对象的程序设计 ECMA-262 把对象定义为:无须属性的集合,其属性可以包含基本值.对象或者函数. 理解对象 var person = new Object(); //创建对象 person.n ...

  7. Javascript 面向对象全新理练之数据的封装

    JavaScript 是一种非常灵活的面向对象程序设计语言,它与传统的强类型的面向对象程序设计语言(如 C++,Java,C# 等)有很大不同,所以要实现如 C++.java.C# 当中的一些特性就需 ...

  8. 《JavaScript面向对象的编程指南》--读书笔记

    第一章.引言 1.5 面向对象的程序设计常用概念 对象(名词):是指"事物"在程序设计语言中的表现形式. 这里的事物可以是任何东西,我们可以看到它们具有某些明确特征,能执行某些动作 ...

  9. JS面向对象的程序设计之继承-继承的实现-借用构造函数

    JS面向对象的程序设计之继承-继承的实现-借用构造函数 前言:最近在细读Javascript高级程序设计,对于我而言,中文版,书中很多地方翻译的差强人意,所以用自己所理解的,尝试解读下.如有纰漏或错误 ...

最新文章

  1. LeetCode: 102. Binary Tree Level Order Traversal
  2. Java Comparator 珍藏版
  3. Java 容器学习之 HashMap
  4. java设计模式6--适配器模式(Adapter )
  5. 【阿里云课程】注意力机制原理,应用与设计
  6. 【ios】Storyboard教程
  7. LeetCode - 121. 买卖股票的最佳时机
  8. 非常适合初学者的机器学习的数学基础笔记.pdf
  9. 软考信息系统项目管理师_考试题型介绍_选择题75分_45分过_案例分析题_75分_45分过_计算题_论文题的架构和写法---软考高级之信息系统项目管理师002
  10. 无向图的割顶、桥、BCC和eBCC相关
  11. WPF下字体模糊的问题
  12. postgres数据库授权失败
  13. 响应面法 matlab,怎么用MATLAB编写响应面优化的程序?
  14. Android StorageManager 存储设备管理
  15. Nifi 数据流整合工具
  16. ps画画模糊笔刷_用ps污点画笔修复工具讲图片变成朦胧效果
  17. Chrome打开浏览器弹出网页、浏览器被劫持解决方法
  18. EEPROM存储芯片24C02
  19. 以枯草芽孢杆菌孢子制造出新冠口服疫苗,香港科研团队重大生物技术突破
  20. LaTex使用方法和技巧——以IEEE会议论文模板为例

热门文章

  1. ARM和NEON指令 very gooooooood.............
  2. 印前处理的“发动机”——RIP
  3. python 对象的异或运算符_python的运算符
  4. 用python做透视表_用Python实现数据的透视表的方法
  5. noclassdeffounderror java,从终端运行Java文件时出现java.lang.NoClassDefFoundError
  6. linux sublime3 插件安装插件,手动安装sublimeText3插件
  7. hal库开启中断关中断_stm32的HAL库开发学习笔记之外部中断
  8. 【混淆矩阵】matlab画混淆矩阵
  9. 3 数组中的重复数字
  10. (十二)洞悉linux下的Netfilteramp;iptables:iptables命令行工具源码解析【下】