JavaScript笔记3--封装JS对象
2016-03-21 17:12
363 查看
1. js原始类型
js有5种原始数据类型:即 Undefined、Null、Boolean、Number 和 String。2. js对象分类
js对象可以分为3类:本地对象、内置对象、宿主对象。本地对象:ECMA-262 把本地对象定义为“独立于宿主环境的,由ECMAScript 提供的对象”。
再来看一下,“本地对象”包含哪些内容:
Object
Function
Array
String
Boolean
Number
Date
RegExp
Error
EvalError
RangeError
ReferenceError
SyntaxError
TypeError
URIError
本地对象就是 ECMA-262 定义的类(引用类型)。
内置对象:ECMA-262 把内置对象定义为“独立于宿主环境的,由ECMAScript 提供的对象,在 ECMAScript 程序开始执行时出现”。
这意味着开发者不必明确实例化内置对象,它已被实例化了。直接使用就行了。
ECMA-262 只定义了两个内置对象,即 Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。
Global对象的属性列表:
Global对象的方法:
例如isNum(),isFinite(),parseInt(),parseFloat()等,都是Global对象的方法。
encodeURI():对传递给浏览器的URI进行编码。对应的解码函数:decodeURI()。
encodeURIComponent():对传递给浏览器的URI进行编码。对应的解码函数:decodeURIComponent()。
这两个方法的主要区别是:
encodeURI()不对URI中的特殊字符编码,例如冒号、斜杠、问号和英镑符号;
encodeURIComponent()会对它发现的所有非标准字符进行编码。而对应有decodeURI()和decodeURIComponent()解码函数。
这些URI方法代替了BOM中的escape()和()方法。URI方法更可取,因为它们会对所有的Unicode符号编码,而BOM方法只能对ASCII符号正确编码。应尽量避免使用escape()方法。
Math对象常用方法:
min()、max()
abs()方法返回数字的绝对值。
ceil()表示向上舍入
floor()表示向下舍入
round()标准的四舍五入
宿主对象:由 ECMAScript 实现的宿主环境提供的对象。所有 BOM 和 DOM 对象都是宿主对象。
BOM对象:window、location、screen、history、navigator。
DOM对象:document、form、button等。
开发人员可以自定义对象。
3.封装JS对象
JavaScript里一切皆对象。所以函数也是对象,是Function的实例。函数名可以理解为指向该实例的引用。JS里封装对象的常用方式有5种:
显示自定义、工厂方法、构造函数方式、原型方式、构造函数+原型方式;
显式自定义对象
var obj1 = { nick: 'Byron', age: 20, printName: function(){ console.log(obj1.nick); } } var obj2 = { nick: 'Casper', age: 25, printName: function(){ console.log(obj2.nick); } }
适用场合:
临时对象。比如作为方法的参数传递时,可以这样封装对象。
全局常量对象。很少做修改情况下适合这样封装对象。比如定义一个AjxxConst对象,该对象的属性是一些常量值,比如案件状态–已公开=3.
缺点:
不能很好的复用;
多个客户端并发访问时,数据容易被修改;
工厂方法封装对象
function createObj(name, age){ var person = new object(); person.name = name; person.age = age; person.printName = function(){ console.log(this.nick); } return person ; } 客户端: var p1 = createObj('权志龙', 30); p1.printName ();
适用场合:
创建操作比较频繁,即经常创建同一类的实例时,可以使用工厂方法。
可以理解为工厂方法是对“创建object对象”这一操作的封装。
缺点:
构造出来的对象类型都是Object,没有识别度;
创建多个实例的同时,还要创建重复的行为printName;
构造函数方式封装对象
<script> function Person(name, age){ this.name = name; this.age = age; this.sayName = function(){ console.log(this.name); console.log(this.age); } } function test(){ var p1 = new Person(); var p2 = new Person('权志龙'); var p3 = new Person('权志龙',30); p1.sayName();//undefined,undefined p2.sayName();//权志龙,undefined p3.sayName();//权志龙,30 } </script>
JS里万物皆对象,方法也是对象。因此可以通过声明一个方法来指定对象类型。
适用场合:
没有固定的场景,自己根据实际情况来决定是否使用吧。
构造方法封装对象,是不是有点儿类似java了呀,还有比这更类似的呢!
缺点:
创建多个实例的同时,还要创建重复的行为printName;
原型方式封装对象
function Person(){ } Person.prototype.name = "权志龙"; Person.prototype.age = 30; Person.prototype.printName = function(){ console.log(this.name); } Person.prototype.printAge = function(){ console.log(this.age); } 客户端: var p1 = new Person(); p1.printName(); p1.printAge();
适用场合:
实例们的属性值固定不变时,适合这样封装对象。
缺点:
参数值绑定的太死了,是不是,是不是,是不是!
构造函数+原型方式封装对象
function MyObject(otherObject){ alert("有参构造函数!"); this.otherObject = otherObject; } MyObject.prototype.name = "y0"; MyObject.prototype.age = "0"; MyObject.prototype.getName = function getName(){ console.log(this.name); }; MyObject.prototype.getAge = function getAge(){ console.log(this.age); }; MyObject.prototype.setName = function setName(name){ this.name = name; }; MyObject.prototype.setAge = function setAge(age){ this.age = age; }; MyObject.prototype.getOtherObject = function getOtherObject(){ console.log(this.otherObject); }; MyObject.prototype.setOtherObject = function setOtherObject(otherObject){ this.otherObject = otherObject; }; 客户端: var myObject1 = new MyObject(); myObject1.getName();//y0 myObject1.getAge();//0 myObject1.setName("yulq"); myObject1.setAge(18); myObject1.getName();//yulq myObject1.getAge();//18 myObject1.getOtherObject();//undefined var myObject2 = new MyObject(11); myObject2.getName();//y0 myObject2.getAge();//0 myObject2.setName("yulq2"); myObject2.setAge(20); myObject2.getName();//yulq2 myObject2.getAge();//20 myObject2.getOtherObject();//11
适用场合:
完美。
缺点:
缺点就是太完美了!
4.定义JS变量
JS变量可以分为三种:私有变量、实例变量、静态变量。<script> function ClassA(){ var a = 1; //私有变量,只有函数内部可以访问 this.b = 2; //实例变量,只有实例可以访问 } ClassA.c = 3; // 静态变量,也就是属性,类型访问 ClassA.prototype.d = 4;//实例变量,只有实例可以访问 function test(){ console.log(a); // error console.log(ClassA.b) // undefined console.log(ClassA.c) //3 console.log(ClassA.d) //undefined var classa = new ClassA(); console.log(classa.a);//undefined console.log(classa.b);// 2 console.log(classa.c);//undefined console.log(classa.d);//4 } </script>
5.JS实现继承
JavaScript并不提供原生的继承机制,我们自己实现的方式很多,介绍一种最为通用的。我们如果实现了两点的话就可以说我们实现了继承:
得到一个类的属性;
得到一个类的方法;
获得父类属性
function Person(name, age){ this.name = name; this.age = age; } Person.prototype.sayName = function (){ console.log(this.name); } --------------------------- function SubPerson(name,age,like){ Person.call(this,name,age); this.like = '唱歌'; } ---------------------------- function test(){ var p1 = new SubPerson('权志龙',30,'唱歌'); console.log(p1.name);//权志龙 }
获得父类属性的原理是:
在子类构造函数里,通过Function.prototype.call(obj,param1,param2…)方法装配子类对象。
call()方法,将某个对象构造方法里的this换成第一个参数指定的对象;
因此,通过调用父类的call给子类装配父类属性,实现了继承属性。
获得父类方法
我们知道类的方法都定义在了prototype里面,所以只要我们把子类的prototype改为父类的prototype的备份就好了。SubPerson.prototype = Object.create(Person.prototype);
我们通过Object.create()方法clone了一个新的prototype而不是直接把Person.prtotype直接赋值。因为引用关系,这样会导致后续修改子类的prototype也修改了父类的prototype,因为修改的是一个值。
这样做需要注意一点就是对子类添加方法,必须在修改其prototype之后,如果在之前会被覆盖掉。
还有个问题,我们知道prototype对象有一个属性constructor指向其类型,因为我们复制的父元素的prototype,这时候constructor属性指向是不对的,导致我们判断类型出错:
SubPerson.prototype.constructor; //Person
因此我们需要再重新指定一下constructor属性到自己的类型:
var _prototype = Object.create(Person.prototype);
_prototype.constructor = SubPerson;
SubPerson.prototype = _prototype;
最终示例如下:
<script> --------------------封装父类对象----------------------- function Person(name, age){ this.name = name; this.age = age; } Person.prototype.sayName = function (){ console.log(this.name); } --------------------封装子类对象----------------------- function SubPerson(name,age,like){ Person.call(this,name,age); this.like = like; } var _prototype = Object.create(Person.prototype); _prototype.constructor = SubPerson; SubPerson.prototype = _prototype; SubPerson.prototype.sayLike = function (){ console.log(this.like); } --------------------客户端----------------------- function test(){ var p1 = new SubPerson('权志龙',30,'唱歌'); console.log(typeof SubPerson); console.log(p1 instanceof SubPerson); p1.sayName(); p1.sayLike(); } </script>
实现要点:
1,在子类的构造方法里,通过Father.call(this,param1,param2……..)获得父类属性;
2,在扩展子类方法之前,通过Object.create(Father.prototype)克隆一个父类原型,将该原型的constructor 指向SubPerson,最后将子类原型指向克隆出来的父类原型,从而子类获得了父类方法。
相关文章推荐
- JS 异常之 missing ) after argument list 错误释疑
- jstl c:choose>、<c:when>和<c:otherwise>标签
- 借助Q.js学习javascript异步编程。
- javascript Deferred和递归次数限制
- 什么是javascript闭包
- jsp表单提交到strust中中文乱码解决
- javaScript将字符串格式的时间转换为date格式
- JavaScript设计模式 Item9 --适配器模式Adapter111
- ExtJs布局之accordion,fit,auto
- java ScriptEngine 使用 (支持JavaScript脚本,eval()函数等) - *(00)*
- 【JavaScript】a标签onclick传递参数不对
- ExtJs之Panel基本布局
- 使用json格式的数据进行通信
- JS中数字计算精度
- js数组基础整理
- 正则表达式的JS验证
- JS DOM实现鼠标滑动图片效果
- 原生js ajax 实例
- 用JS写递归中容易出错的点
- js判断变量类型,类型转换,