DOM笔记(十一):JavaScript对象的基本认识和创建
一、什么是对象?
面 向对象(Object-Oriented,OO)的语言有一个标志,那就是都有类的概念,例如C++、Java等;但是ECMAScript没有类的概 念。ECMAScript-262把对象定义为:无序属性的集合,其属性可以包含基本值、对象或者函数。通俗一点的理解就是,ECMAScript中的对 象就是一组数据和功能的集合,通过new操作符后跟要创建的对象类型的名称来创建。每个对象都基于一个引用类型创建。引用可以是原生类型(相关介绍:引用类型),或者开发人员自定义的类型。
二、Object对象
跟其他OO语言一样,Object对象类型是所有它的实例的基础。Object对象类型所具有的任何属性和方法同样也存在于更具体的对象中。
- //创建object对象
- var o = new Object();
- //若没有参数传递,可以省略圆括号,但不推荐使用
- var o = new Object;
Object的每个实例都具有共同的基本属性和方法
属性或者方法 | 说明 |
constructor | 指向创建当前对象的构造函数 |
hasOwnProperty(name) | 检测给定属性name在实例对象(不是原型对象)中是否存在。name以字符串形式指定 |
isPropertyOf(object) | 检测传入的对象object是否该方法调用者的原型对象。一般格式:Class.prototype.isPropertyOf(object) |
propertyIsEnumerable(pr) | 检测属性pr能否用for-in循环枚举。属性pro用字符串形式指定 |
toLocaleString() | 返回对象的字符串表示。与地区和环境对应 |
toString() | 返回对象的字符串表示 |
valueOf() | 返回对象的字符串、数值或布尔值表示 |
三、对象的属性类型
在ECMAScript 5中,定义了用于描述属性的各种特征的内部特性,为实现JavaScript引擎服务,所以这些特性在JavaScript中不能直接访问。属性类型有两种:数据属性和访问器属性。
1、数据属性
数据属性包含一个数据值的位置,在这个位置对数据进行读取和写入。ECMAScript定义了4个特性来描述数据属性的行为:
特性 | 说明 |
[[Configurable]] | 表示能否通过delete删除属性从而重新定义属性、能否修改属性的特性、能否把属性修改为访问器属性。默认值是true |
[[Enumerable]] | 表示能都通过for-in循环返回属性。默认值是true |
[[Writable]] | 表示能否修改属性。默认值是true |
[[Value]] | 表述属性的数据值。默认值是undefined |
2、访问器属性
访问器属性不包含数据值,不能直接定义。读取访问器属性时,调用getter函数,该函数负责返回有效值;写入访问器属性时,调用setter函数并传入新值。访问器也有4个属性:
特性 | 说明 |
[[Configurable]] | 表示能否通过delete删除属性从而重新定义属性、能否修改属性的特性、能否把属性修改为访问器属性。默认值是true |
[[Enumerable]] | 表示能都通过for-in循环返回属性。默认值是true |
[[Get]] | 读取属性时调用的函数,默认是undefined |
[[Set]] | 写入属性时调用的函数,默认是undefined |
怎么获取对象属性的默认特性呢?
- var person = {
- name:"dwqs",
- age:20,
- interesting:"coding",
- blog:"www.ido321.com"
- };
- var desc = Object.getOwnPropertyDescriptor(person,"age");
- alert(desc.value); //20
- alert(desc.configurable); //true
- alert(desc.enumerable); //true
- alert(desc.writable); //true
使用ECMAScript 5的Object.getOwnPropertyDescriptor(object,prop)获取给定属性的描述符:object 是属性所在的对象,prop是给定属性的字符串形式,返回一个对象。若prop是访问器属性,返回的对象包含configurable、 enumerable、set、get;若prop是数据属性,返回的对象包含configurable、enumerable、writable、 value。
属性的特性都不能直接定义,ECMAScript提供了Object.defineProperty(obj,prop,desc):obj是属性所在的对象,prop是给定属性的字符串形式,desc包含特性集合的对象。
var person = {
name:“dwqs”,
age:20,
interesting:“coding”,
blog:“www.ido321.com”
};
//定义sex属性,writable是false,所以不能修改
Object.defineProperty(person,“sex”,{
writable:false,
value:“male”
});
alert(person.sex); //male
//在严格模式下出错,非严格模式赋值被忽略
person.sex=“female”; //writable是false,所以不能修改
alert(person.sex); //male
可以多次调用Object.defineProperty()修改特性,但是,若将
configurable定义为false,则不能再调用Object.defineProperty()方法将其修改为true。此外,调用
Object.defineProperty()时若不指定特性的值,则configurable、enumerable和writable的默认值是
false。
- var person = {
- name:"dwqs",
- age:20,
- interesting:"coding",
- blog:"www.ido321.com"
- };
- Object.defineProperty(person,"sex",{
- configurable:false,
- value:"male"
- });
- alert(person.sex); //male
- delete person.sex; //configurable是false,严格模式下出错,非严格模式下忽略此操作
- alert(person.sex); //male
- //抛出Cannot redefine property: sex错误
- Object.defineProperty(person,"sex",{
- configurable:true,
- value:"male"
- });
- alert(person.sex); //不能弹框
- delete person.sex;
- alert(person.sex);//不能弹框
也可以用Object.defineProperties(obj,props)同时定义多个属性:obj是属性所在的对象,props是一个包含多个属性定义的对象
var book={};
Object.defineProperties(book,{
_year:{
value:2014
},
edition:{
value:1
},
year:{
get:function()
{
return this._year;
},
set:function(newValue)
{
if(newValue > 2014)
{
this._year = newValue;
this.edition += newValue – 2014
}
}
}
});
var descs = Object.getOwnPropertyDescriptor(book,“_year”);
alert(descs.value); //2014
//调用Object.defineProperty()时若不指定特性的值,则configurable、enumerable和writable的默认值是false。
alert(descs.configurable); //false
alert(typeof descs.get); //undefined
get和set可以不指定,也可以值指定二者之一。只有get表示属性是只读的,只有set表示属性只能写入不能读取。
- var person = {
- name:"dwqs",
- age:20,
- interesting:"coding",
- blog:"www.ido321.com"
- };
- Object.defineProperty(person,"sex",{
- configurable:false,
- value:"male"
- });
- alert(Object.keys(person)); //name,age,interesting,blog
- alert(Object.getOwnPropertyNames(person)); //name,age,interesting,blog,sex
因为sex属性是用defineProperty()方法定义,而对于未指定的enumerable的值默认是false。所以第一次弹框没有返回sex属性,而第二次返回了。
四、创建对象的方式
1、工厂模式
- function Person(name,age,blog)
- {
- var o = new Object();
- o.name = name;
- o.age = age;
- o.blog = blog;
- o.interest = function()
- {
- alert("I like coding and writing blog!!!");
- }
- return o;
- }
- var per1 = Person("dwqs",20,"www.ido321.com");
- alert(per1.name); //dwqs
优点:节省代码量,防止冗余。
缺点:不能识别对象,即创建的每个实例都有相同的属性,不能反应对象的类型。
2、构造函数模式
- function Person(name,age,blog)
- {
- this.name = name;
- this.age = age;
- this.blog = blog;
- this.interest = function()
- {
- alert("I like coding and writing blog!!!");
- }
- }
- var per1 = new Person("dwqs",20,"www.ido321.com");
- alert(per1.name);
优点:创建的每个实例都不同,可以识别不同对象。
缺点:创建一个实例,实例共有的方法都会重新创建。对应的解决方案可以把方法定义到全局上去,或者定义在原型对象上。
- function Person(name,age,blog)
- {
- this.name = name;
- this.age = age;
- this.blog = blog;
- this.interest = my;
- }
- function my()
- {
- alert("I like coding and writing blog!!!");
- }
这样,Person的所有实例均共享了my()方法。
3、原型模式
- function Person()
- {
- }
- Person.prototype.name = "dwqs";
- Person.prototype.age = 20;
- Person.prototype.blog = "www.ido321.com";
- Person.prototype.interest = function()
- {
- alert("I like coding and writing blog!!!");
- }
- var per1 = new Person();
- alert(per1.name); //dwqs
- var per2 = new Person();
- alert(per1.interest == per2.interest); //true
per1和per2共享了所有原型上定义的属性和方法,显然,不能保持每个实例的独立性了,不是我们想要的。具体关于原型,后续笔记在解释。
4、原型模式+构造函数模式(推荐使用)
- function Person(name,age,blog)
- {
- this.name = name;
- this.age = age;
- this.blog = blog;
- }
- Person.prototype.interest = function()
- {
- alert("I like coding and writing blog!!!");
- }
- var per1 = new Person("dwqs",20,"www.ido321.com");
- alert(per1.name); //dwqs
- var per2 = new Person("i94web",22,"www.i94web.com");
- alert(per2.blog); //www.i94web.com
构造函数定义每个实例的不同属性,原型共享共同的方法和属性,最大限度的节省内存。
5、动态原型模式
- function Person(name,age,blog)
- {
- this.name = name;
- this.age = age;
- this.blog = blog;
- if(typeof this.interest != "function")
- {
- Person.prototype.interest = function()
- {
- alert("I like coding and writing blog!!!");
- };
- }
- }
- var per1 = new Person("dwqs",20,"www.ido321.com");
- per1.interest(); //I like coding and writing blog!!!
将所有信息均封装在构造函数中,在需要的时候,初始化原型。
6、寄生构造函数模式
- function Person(name,age,blog)
- {
- var o = new Object();
- o.name = name;
- o.age = age;
- o.blog = blog;
- o.interest = function()
- {
- alert("I like coding and writing blog!!!");
- }
- return o;
- }
- var per1 = Person("dwqs",20,"www.ido321.com");
- alert(per1.name); //dwqs
形式跟工厂模式一样,但这个可以在特殊情况下用来为对象创建构造函数,并且使用new操作符创建对象,而工厂模式没有使用new,直接使用返回的对象。例如,在不能修改原生对象Array时,为其添加一个新方法
- function SpecialArray()
- {
- var values = new Array();
- values.push.apply(values,arguments);
- values.toPipedString = function()
- {
- return this.join("|");
- };
- return values;
- }
- var colors = new SpecialArray("red","blue","yellow");
- alert(colors.toPipedString()); //red|blue|yellow
需要说明的是,寄生构造函数模式返回的对象与构造函数或者构造函数的原型对象没有关系,所以不能用instanceof操作符来确定对象类型。
7、稳妥构造函数模式
- function Person(name,age,blog)
- {
- var o = new Object();
- o.sayName = function()
- {
- alert(name);
- }
- return o;
- }
- var per1 = Person("dwqs");
- per1.sayName(); //dwqs
以这种方式创建的对象,除了sayName()方法之外,没有其他办法访问name的值。per1称为稳妥对象。稳妥对象指没有公共属性,其方法也不引用this的对象。
稳妥构造函数模式与寄生构造函数有两点区别:新建对象的实例方法不引用this;不使用new操作符调用构造函数。
原文首发:http://www.ido321.com/1365.html
DOM笔记(十一):JavaScript对象的基本认识和创建的更多相关文章
- 【知了堂学习笔记】/JavaScript对象--/暖妮
JavaScript对象 1.什么是JavaScript对象? JavaScript 中的所有事物都是对象:字符串.数字.数组.日期,等等. 在 JavaScript 中,对象是拥有属性和方法的数据. ...
- 1.3 (JavaScript学习笔记)JavaScript对象
在JavaScript中所有事物都是对象,字符串.数值.数组.函数...等, JavaScript还允许自定义对象.这些在1.1中有所介绍. 一.遍历对象属性 <!DOCTYPE html> ...
- DOM笔记(十三):JavaScript的继承方式
在Java.C++.C#等OO语言中,都支持两种继承方式:接口继承和实现继承.接口继承制继承方法签名,实现继承则继承实际的方法和属性.在SCMAScript中,由于函数没有签名,所以无法实现接口继承, ...
- 【代码笔记】Web-JavaScript-Javascript对象
一,效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...
- JavaScript进阶系列03,通过硬编码、工厂模式、构造函数创建JavaScript对象
本篇体验通过硬编码.工厂模式.构造函数来创建JavaScript对象. □ 通过硬编码创建JavaScript对象 当需要创建一个JavaScript对象时,我们可能这样写: var person = ...
- DOM笔记(十二):又谈原型对象
因为之前谢过一篇关于原型对象的笔记:浅谈JavaScript中的原型模式.现在我又重新看到这个话题,对原型有了进一步的理解,所以,又要谈谈原型对象. 一.理解原型对象 创建的每一个函数都有一个prot ...
- 读书笔记:JavaScript DOM 编程艺术(第二版)
读完还是能学到很多的基础知识,这里记录下,方便回顾与及时查阅. 内容也有自己的一些补充. JavaScript DOM 编程艺术(第二版) 1.JavaScript简史 JavaScript由Nets ...
- DOM笔记(十):JavaScript正则表达式
一.RegExp ECMAScript通过RegExp类型类支持正则表达式,语法和Perl类似: var exp = /pattern/flags; patternb部分是任何简单的或复杂的正则表达式 ...
- DOM笔记(八):JavaScript执行环境和垃圾收集
一.执行环境 在有关于JavaScript对象或者this的指向问题时,脱离不了的另外一个概念就是执行环境,即上下文环境.执行环境在JavaScript是一个 很重要的概念,因为它定义了变量或函数有权 ...
随机推荐
- TCP/IP、Http、Https、Socket的区别
网络由下往上分为物理层.数据链路层.网络层( IP协议).传输层( TCP协议).会话层.表示层和应用层(HTTP协议) 接下来我来说说个人理解其中的TCP/IP.Http.Socket的区别 TCP ...
- vue首次赋值不触发watch(deep immediate handler)
deep:默认值是 false,代表是否深度监听.immediate:true代表如果在 wacth 里声明了之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样, ...
- chrome浏览器解决 跨域调试问题
1.关闭chrome浏览器(全部) 我们可以通过使用chrome命令行启动参数来改变chrome浏览器的设置,具体的启动参数说明参考这篇介绍.https://code.google.com/p/xia ...
- Jquery 获取table中的td元素的值
<table id="t1"> <tr> <td> 1-1 </td> <td> 1-2 </td> < ...
- jmeter-集合点---学习笔记
集合点: 简单来理解一下,虽然我们的“性能测试”理解为“多用户并发测试”,但真正的并发是不存在的,为了更真实的实现并发这感念,我们可以在需要压力的地方设置集合点,每到输入用户名和密码登录时,所有的虚拟 ...
- regular expression, grep (python, linux)
https://docs.python.org/2/library/re.html re.match(pattern, string, flags=0) 尝试从字符串的起始位置匹配一个模式 re.s ...
- [转]jQuery的.live()和.die()
本文转自:http://www.cnblogs.com/dumuqiao/archive/2011/09/09/2172513.html 翻译原文地址:http://www.alfajango.com ...
- Python collections
#count对象 Only 2.7 from collections import Counter #统计字母出现的次数 Counter('hello world') Counter(['red', ...
- [一点一滴.NET]前台线程和后台线程
前台线程和后台线程就是通过线程实例的属性IsBackground=true or false来区分的. 新建一个线程是默认是后台线程. 前台线程全部执行完之后,才退出进程. 进程退出,所有的后台线程全 ...
- jQuery 间歇式无缝滚动特效分享(三张图片平行滚动)
最近项目中门户首页需要做出图片间歇式无缝滚动特效,但是在网上找资料都是不太理想,不过可以指导.最后自己写了一个demo实现了这个特效,分享出来. 1.jquery.cxscroll.js /*! * ...