JavaScript对象(一)
对象
对象是动态的——可以新增属性也可以删除属性,但是对象经常用来模拟静态对象以及静态类型语言中的“结构体”。对象的属性是可以增加和删除的。
对象特性
对象原型(prototype
):指向另外一个对象,本对象的属性继承自它的原型对象。
对象的类(class
):是一个表示对象类型的字符串。
*对象的扩展标记(extensible flag
):指明是否可以向该对象添加新属性。
属性特性
可写 (是否可以设置属性值)
可枚举 (是否可以通过for in 循环返回该属性)
可配置 (是否可以删除或者修改属性)
对象的创建
对象直接量
创建对象最简单的方法是通过对象直接量。
var empty = {}; //没有任何属性的对象var point = {x:0, y:0}; // 两个属性var point2 = {x:point.x, y:point.y+1}; var student = {name:"Allen", //属性名可以不用引号age:23,school:{ //这个属性值是一个对象,"primary school" :"试验小学",//属性名中有空格,必须字符串"middle-school" :"育才中学" ,//属性名中有连接符,必须用字符串
}
}
/*最后注意一点,属性名尽量避免使用空格、连接符、或者关键字,如果必须使用的话,尽量用引号引起来*/
通过new 创建对象
var mObj = new Object(); // 创建一个空对象,和{}一样var arr = new Array(); // 创建一个空数组,和[]一样
var mDate = new Date(); // 创建一个表示当前时间的Date对象
通过 Object.create()
在这里,我们先弄清楚一个名词——原型,每一个JS对象(除了null
)都和另一个对象相关联。“另一个”对象就是我们所说的原型,每一个对象都从原型继承属性。
所有通过对象直接量创建的对象都具有同一个原型对象,并可以通过JS代码Object.prototype
获得对原型对象的引用。通过关键字new
和构造函数调用创建的对象的原型就是构造函数的prototype
属性的值。因此,同使用{}创建对象一样,通过new Object()
创建对象也继承自Object.prototype
。
ECMAScript 5 定义了一个名为Object.create()
的方法,它创建一个新的对象,其中第一个参数就是对象原型,第二个参数是可选参数,用以对对象的属性进行进一步描述。
Object.create()`是静态函数,而不是提供给某一个对象调用的方法。
var obj = Object.create({x:1,y:2}); // obj继承了属性x,y
var obj2 = Object.create(obj); //obj2的原型是obj,继承了属性x,y;
// 如果想创建一个普通的空对象(比如通过{}或者new Object()创建的对象 ),需要传入Object.prototype
var obj3 = Object.create(Object.prototype);//obj3和{}和new Object()一样
现在我们来看看如何自己写一个函数来通过原型来创建对象,看例子
function createObject(obj){// 先对obj对象进行判断,看是否为null,如果是抛出异常if(obj == null) throw TypeError();// Object.create是否可用,可用则返回if(Object.create) return Object.create(obj);// 不可用时,检测对象的类型var objType = typeof obj;// 如果对象类型不是Object 也不是函数的话,抛出异常if(objType !=="object" && objType !=="function") throw TypeError();// 定义一个空构造函数 并且将函数的原型设置成objfunction mfunc(){};mfunc.prototype = obj;return new mfunc();}
属性
对象访问属性的方法有两个,通过(.
)和([]
)运算符来获取属性值。这里不做解释。
下来我们详细讲解一下通过([]
)获取属性值,这种获取属性值的方法很像数组,只是数组的索引是数字,而它的索引是字符串。这种数组就是我们将要说明的关联数组,也成散列、映射或字典。由于JS是弱类型语言,在任何对象中程序都可以创建任意数量的属性。通过([]
)来访问对象的属性时,属性名是字符串,这样更利于我们在程序运行时进行修改和创建属性。
我们举个例子来说明它的灵活性吧,假设我们去超市购买东西,我们把需要买的东西放入购物车,这辆购物车的作用就是显示我们放入的商品名称,以及商品的单价和数量。你有没有思路呢?学过类似C语言的同学,可以想想如何来实现。简单说一下我的思路吧(用类似C语言的方式的思路,大神勿喷,可以留下你的思路),此处的购物车我们用一个类似字典的对象来表示,字典的Key就是我们的商品名称,Value则是一个对象,对象中的属性包含:商品价格、数量。现在想想用JavaScript如何,思路其实同我上面说的类似,直接看代码吧。
var shoppingCart = {};//这里是购物车
// 添加商品的方法
function addGoods(name,price,count){shoppingCart[name] = {m_price:price,m_count:count};
}
(一)继承(属性的查询和设置)
JS对象有自有属性和继承属性,我觉得通过举例更容易说明这两个属性的关系。
查询对象的属性举例:
假设要查询对象obj
的属性x
,如果obj
中不存在x
,那么将会继续在obj
的的原型对象中查询属性x
,如果原型对象也没有x
,但是这个原型对象也有原型(原型不为null
),那么继续在这个原型对象的原型上执行查询,直到找到x或者查找到一个原型为null
的对象为止。
给对象的属性赋值举例:
假设给对象obj的属性x
赋值,如果obj
中已经有属性x
(这个属性不是继承来的),那么这个赋值操作只改变这个已有属性x
的值。如果obj
中不存在属性x
,那么赋值操作给obj
添加一个新属性x。如果之前obj
继承自属性x
,那么这个继承的属性就会被新创建的同名属性覆盖。
小总结:对象的属性赋值,不会修改原型的属性值的,只会创建属性或者对自有属性赋值。但是需要注意的是,属性赋值操作首先是检查原型链,以此判断是否允许赋值,如果继承的属性是只读的,则赋值操作是不允许的
看一个例子:
var obj = {x:1,y:2};
var obj2 = Object.create(obj);
console.log(obj); // ==> {x:1,y:2}
console.log(obj2); // ==> {x:1,y:2}
//----看点 1-----
// 现在对obj2 属性x值进行修改,看看obj 和 obj2的变化
obj2.x = 100;
console.log(obj); // ==> {x:1,y:2}
console.log(obj2); // ==> {x:100,y:2}
/*可以看出————对象的属性不会修改原型的属性*/
// -------------------------------------------------------
//----看点 2-----
// 这个时候我们对obj 属性x进行修改,看看变化
obj.x = 111;
console.log(obj); // ==> {x:111,y:2}
console.log(obj2); // ==> {x:100,y:2}
/*可以看出————对象属性赋值的时候只会创建属性或者对自有属性进行赋值,因为在之间对obj2的x属性进行赋值的时候,obj2的自有属性中没有x属性,所以obj2会创建新的属性x并赋值,同时覆盖掉继承属性x的值*/
// -------------------------------------------------------
//----看点 3-----
// 我们现在对obj 属性y进行修改,看看变化
obj.y = 222;
console.log(obj); // ==> {x:111,y:222}
console.log(obj2); // ==> {x:100,y:222}
/*这里就可以体现我们上面说到的对象属性的查询过程,因为obj的y属性修改为222,当我们查询obj2的y属性的时候,obj2的自有属性中没有y值,所以obj2就会到它的原型(obj)中查找,原型中的y属性经过修改变成222,所以查询的obj2属性y的结果就是222*/
// -------------------------------------------------------
//----看点 4-----
// 我们来看看访问一个不存在的属性,
console.log(obj2.m_string); // ==> undefined
console.log(obj2.m_string.length); // ==> 这里会报错
/*当访问的属性不存在的时候,系统会返回一个undefined,而null和undefined值是没有属性的,因此上述第二行代码会报错。*/
// 我们可以通过判断的方法来避免错误的出现
var strLength;
if(obj2 && obj2.m_string) strLength = obj2.m_string.length;
//还有一种更简练的方法
strLength = obj2 && obj2.m_string && obj2.m_string.length;
经过上面的例子,你是否搞懂继承了?
#####(二)属性的删除、检测、枚举
删除属性
说先我们来了解一下delete
运算符,该运算符可以删除对象的属性。但是delete
只是断开属性和宿主对象的关系,而不会去操作属性中的属性。delete
表达式删除成功时会返回true。
需要注意的是,delete
运算符只能删除自有属性,不能删除继承属性,也不能删除不可配置的属性。
// 删除属性的操作
var mframe = {point:{x:11,y:22},size:{width:100,heght:50}};
// 这里用p对象引用mfram的point属性
var p = mframe.point;
// 当我们执行删除操作之后,来打印p看看结果
delete mframe.point;
console.log(p); // ==> {x:11,y:22};
/*执行代码之后,我们知道mframe已经没有了point属性,但是由于已经删除的属性的引用依然存在,因此在JS的某些实现中,可能因为这种不严谨的代码而造成内存泄漏,所以在销毁对象的时候,要遍历属性中的属性,依次删除*/
检测属性
检测属性主要是来判断某属性是否存在于某个对象中,我们用代码来介绍一下检测属性。
// in运算符来检测属性,左侧是 属性名(字符串),右侧是对象
var mpoint = {x:1,y:2};
console.log("x" in mpoint); //==> true
console.log("z" in mpoint); //==> false
console.log("toString" in mpoint); //==> true,toString是继承属性;
// -------------------------------------------------------
// hasOwnProperty()方法用来检测给定的名字是否是对象的自有属性,对于继承属性它将返回false。
console.log(mpoint.hasOwnProperty("x")); //==> true
console.log(mpoint.hasOwnProperty("z")); //==> false
console.log(mpoint.hasOwnProperty("toString")); //==> false
// -------------------------------------------------------
// propertyIsEnumerable()是hasOwnProperty()的加强版,只有检测到是自有属性且这个属性是可枚举的才会返回ture.这里就不做举例了
枚举属性
我们经常会遍历对象的属性,通常使用for/in
循环来遍历。for/in
循环可以遍历对象中所有可枚举的属性(包括自有属性和继承属性)。
有许多实用工具库给Object.prototype
添加了新的方法或属性,这些属性可以被所有对象继承并使用,但是在ECMAScript 5标准之前,这些新添加的方法是不能定义为不可枚举的,因此使用for/in
循环进行枚举的时候,这些属性会被枚举出来。为了避免这种情况,我们需要在for/in
中进行过滤,有两种常见的方法:
for(p in obj){if(!obj.hasOwnProperty(p)) continue; // 跳过继承的属性
}
//---------------------------------
for(p in obj){if(typeof obj[p] === "function") continue; // 跳过方法
}
除了for/in
循环之外,ECMAScript 5 定义了两个用以枚举属性名称的函数。
Object.keys()
,它返回一个数组,这个数组由对象中可枚举的自有属性的名称组成。
Object.getOwnPropertyNames()
,它返回对象的所有自有属性的名称(包括自有属性中的可枚举属性和不可枚举属性).
JavaScript对象(一)相关推荐
- 如何获取HTML元素对应JavaScript对象?
<!DOCTYPE html> <html><head><meta charset="UTF-8"><title>< ...
- JavaScript对象,方括号和算法
by Dmitri Grabov 德米特里·格拉波夫(Dmitri Grabov) JavaScript对象,方括号和算法 (JavaScript Objects, Square Brackets a ...
- 我对javascript对象的理解
前言 JavaScript这门语言除了基本类型都是对象,可以说JavaScript核心就是对象,因此理解JavaScript对象及其种种特性至关重要,这是内功.本文介绍了我对es5对象,原型, 原型链 ...
- 《JavaScript启示录》——1.21 JavaScript对象和Object()对象
本节书摘来自异步社区<JavaScript启示录>一书中的第1章,第1.21节,作者:[美]Cody Lindley著,更多章节内容可以访问云栖社区"异步社区"公众号查 ...
- 《JavaScript启示录》——第1章 JavaScript对象 1.1创建对象
本节书摘来自异步社区<JavaScript启示录>一书中的第1章,第1.1节,作者:[美]Cody Lindley著,更多章节内容可以访问云栖社区"异步社区"公众号查看 ...
- 如何通过其值获取JavaScript对象中的键?
本文翻译自:How to get a key in a JavaScript object by its value? I have a quite simple JavaScript object, ...
- 如何从JavaScript对象中删除项目[重复]
本文翻译自:How to remove item from a JavaScript object [duplicate] Possible Duplicate: 可能重复: How to remov ...
- 如何遍历JavaScript对象?
本文翻译自:How to iterate over a JavaScript object? I have an object in JavaScript: 我在JavaScript中有一个对象: { ...
- 打印JavaScript对象的内容? [重复]
本文翻译自:Print content of JavaScript object? [duplicate] This question already has an answer here: 这个问题 ...
- 通过属性值从对象数组中获取JavaScript对象[重复]
本文翻译自:Get JavaScript object from array of objects by value of property [duplicate] This question alr ...
最新文章
- 读书笔记之:C/C++程序员实用大全—C/C++最佳编程指南
- 什么是mysql分发版_MySQL:使用源码分发版还是二进制分发版
- android socket_附详尽答案,新版精选Android中高级面试题二
- 任务队列和异步接口的正确打开方式(.NET Core版本)
- ASM_PREFERRED_READ_FAILURE_GROUPS
- 关于六年级定格动画计算机教案,定格动画教案
- 解决pathForResource返回nil / 无法读取plist文件问题
- IntelliJ IDEA常用快捷键——基于Eclipse
- python3怎么使用mnist_loader_Python读取mnist
- 基于JAVA+SpringMVC+Mybatis+MYSQL的漫画社区
- 迪士尼收购福克斯,传媒巨头江山瓦解?
- Mongodb Manual阅读笔记:CH2 Mongodb CRUD 操作
- 一组开源asp.net用户控件
- SpringBoot 2.0.0 注入SpingCloud 有bug(目前只有SpringBoot 1.5+ 版本的支持)
- 数据库SQL语言的使用
- 概率论——马尔科夫链
- 【产业互联网周报】阿里云栖大会、百度世界大会召开:阿里重推“云端一体”、百度AI全面升级...
- html校验邮箱格式,邮箱格式验证 方法总结
- 通过 经纬度 获取 地理位置(Python、高德地图)
- 第十五天PAT-A1124 Raffle for Weibo Followers简单模拟测试点三错误说明