Javascript基础——Javascript语言核心(3):对象

对象

6.1 创建对象

创建对象的方法:对象直接量、关键字new和Object.create()

6.1.1 对象直接量

属性名在不是保留字、没有空格和连接符等情况下可以没有引号。

var empty={}         //没有属性的对象
var point={x:0, y:1} //两个属性的普通对象

var book={
    "main title" : "JS",    //属性名有空格,必须用字符串
    "sub-title" : "Guide",  //属性名有连接符,必须用字符串
    "for" : "all",          //属性名是保留字,必须用字符串
    author:{                //属性值是一个对象
        firstname: "Joe",    //属性名可以没有引号
        surname: "Flanagan"
    }
}   
6.1.2 通过new创建对象

new运算符创建并初始化一个新对象。关键字new后跟随一个函数调用,这个函数成为构造函数(construcor),用来初始化一个新建的对象。

Javascript语言核心中的原始类型都包含内置构造函数:

var o = new Object(); // 创建一个空对象,和{}一样
var a = new Array();  // 创建一个空数组,和[]一样
var d = new Date();   // 创建一个表示当前时间的Date对象

用自定义构造函数来初始化新对象也很常见。

6.1.3 原型

每一个Javascript对象(null除外)都和另一个对象相关联。“另一个”对象就是原型,每个对象都从原型继承属性。

对象创建方式原型备注
对象直接量Object.prototype
关键字new和构造函数构造函数的prototype通过new Object()创建,原型为Object.prototype
通过new Array()创建,原型为Array.prototype
通过new Date()创建,原型为Date.prototype

Object.prototype没有原型,像Date.prototype继承自Object.prototype。所以具有以下关系:

new Date()创建的对象 继承自 -> Date.prototype 继承自 -> Object.prototype

这一系列链接的原型对象就是所谓的“原型链”(prototype chain)

6.1.4 Object.create()
方法用途参数1参数2(可选)
Object.create()创建一个新对象这个对象的原型对对象的属性进行进一步描述
var obj1=Object.create({x:1, y:2}); //obj1继承了属性x和y

//创建一个空对象
var obj2=Object.create(Object.prototype); //和{}及new Object()一样

6.2 属性的查询和设置

通过.[]可以获取和设置属性值。

var obj={};

obj.x=1;    //设置属性
obj["y"]=2; //设置属性

obj.y         //=> 2: 查询属性
obj["x"]    //=> 1: 查询属性

注意,.后面不能是保留字,obj.for非法的。只能用[],例如obj["for"]

6.2.2 继承

Javascript对象具有“自有属性”(own property),也有一些属性是从原型对象继承而来的。属性的查找沿着原型链一直向上。

6.2.3 属性访问错误

如果在对象自身的属性和继承的属性中都没有找到某个属性,则返回undefined。

var obj = {};
obj.x;       //=> undefined
obj.x.length //报错

对象为null,或者查询null和undefined的属性,都会报错。

var obj=null;
obj.x;       //报错

常用下面的方式来避免报错:

var len= obj && obj.x && obj.x.length;

内置构造函数的原型是只读的。

Object.prototype = 0; //赋值失败,但不报错

6.3 删除属性

delete运算符可以删除属性对象。需要注意,delete只是断开属性和宿主对象的联系,而不会操作属性中的属性。

var obj={ p:{x:1} };
var b = obj.p;

delete obj.p;
obj.p;        //=> undefined
b.x;          //=> 1

所以在销毁对象时,要遍历属性中的属性,依次删除,否则会造成内存泄露

成功删除或没有任何副作用(比如删除不存在的属性)返回true。不能删除可配置性为false的属性。

delete 1;                //=> true
delete Object.prototype; //=> false

6.4 检测属性

检测某个属性是否在某个对象中,有几种方式:

检测方式说明备注
!==运算符(不推荐)检测自有和继承属性判断属性是否是undefined
in运算符检测自有和继承属性4.9.3中介绍过,比起!==可以区分是不存在的属性,还是存在但值为undefined
hasOwnProperty()仅检测自有属性
propertyIsENumerable()仅检测自有属性且该属性可枚举某些内置属性不可枚举,通常由Javascript代码创建的属性都是可枚举的。
var obj = {x:1};

obj.x !== undefined            //=> true
obj.toString !== undefined     //=> true: 继承属性

"x" in obj;                    //=> true
"toString" in obj              //=> true: 继承属性

obj.hasOwnProperty("x")        //=> true
obj.hasOwnProperty("toString") //=> false: 继承属性

Object.prototype.propertyIsEnumerable("toString") //=> false: 不可枚举

6.5 枚举属性

遍历对象的属性,有以下几种方式:

方式说明
for/in循环遍历
Object.keys()返回一个数组,由对象中可枚举的自有属性的名称组成。
Object.getOwnPropertyNames()返回一个数组,由对象中所有自有属性,不仅仅是可枚举的属性的名称组成。
var obj={x:2,y:3};

for(att in obj){
    console.log(att);                         //=> x y
}

Object.keys(obj)                             //=> ["x","y"]
Object.keys(Object.prototype)                //=> []

Object.getOwnPropertyNames(obj)              //=> ["x","y"]
Object.getOwnPropertyNames(Object.prototype) //=> ["constructor", "__defineGetter__", "__defineSetter__", "hasOwnProperty", "__lookupGetter__", "__lookupSetter__", "isPrototypeOf", "propertyIsEnumerable", "toString", "valueOf", "__proto__", "toLocaleString"]

6.6 属性getter和setter

属性值可以用一个或两个方法(getter和setter)代替。由getter和setter定义的属性称作“存取器属性”(accessories property),它不同于“数据属性”(data property)——只有一个简单的值。

var p={
    x:1,
    y:2,
    get sum(){
        return this.x+this.y;
    },
    set sum(base){
        this.x += base;
        this.y += base;
    }
}

p.x       //=> 1
p.sum     //=> 3

p.sum = 5
p.x       //=> 6
p.sum     //=> 13

和数据属性一样,存取器属性是可以继承的。

6.7 属性的特性

一个属性包含1个名称和4个特性

属性分类特有特性共有特性
数据属性值(value)、可写性(writable)可枚举性(enumerable)、可配置性(configurable)
存取器属性读取(get)、写入(set)同上

为实现属性特性的查询和设置。ECMAScript 5定义了一个名为“属性描述符”(property descriptor)的对象来代表那4个特性。

6.7.1 查询属性描述符

调用Objet.getOwnPropertyDescriptor()获得某个对象特定属性的自有属性描述符。

configurable: true}
Object.getOwnPropertyDescriptor({x:1},"x") //=> {value: 1, writable: true, enumerable: true, 

//6.6中的p对象
Object.getOwnPropertyDescriptor(p,"sum")   //=> {get: ƒ, set: ƒ, enumerable: true, configurable: true}

//继承属性和不存在的属性,返回undefined
Object.getOwnPropertyDescriptor({},"x")           //=> undefined
Object.getOwnPropertyDescriptor({x:1},"toString") //=> undefined
6.7.2 设置单个属性描述符

设置属性特性或想让新建属性具有某种特性,需要调用Object.defineProperty()。注意,不能修改继承属性。

参数: 要修改的对象;创建或修改的属性名称;属性描述符对象。

var obj={};

//添加一个不可枚举的数据属性x,并赋值为1
Object.defineProperty(obj,"x",{ value: 1,
                                writable: true,
                                enumerable: false,
                                configurable: true});

//属性存在,但不可枚举
obj.x            //=> 1
Object.keys(obj) //=> []

//修改x属性为只读
Object.defineProperty(obj,"x",{writable: false});
obj.x = 2; //操作失败但不会报错
obj.x      //=> 1

//可以通过配置修改值
Object.defineProperty(obj,"x",{value: 2});
obj.x      //=> 2

//将x从数据属性修改为存取器属性
Object.defineProperty(obj,"x",{get: function(){return 0;}});
obj.x //=> 0
6.7.3 设置多个属性描述符

如果需要同时修改或创建多个属性,使用Object.defineProperties()

参数:要修改的对象;参数映射表

var p = Object.defineProperties({},{
    x:{value:1, writable:true, enumerable:true, configurable:true},
    y:{value:2, writable:true, enumerable:true, configurable:true},
    sum:{
        get: function(){ return this.x+this.y},
        enumerable:true,
        configurable:true
    }
})

6.8 对象的三个属性

每个对象都有与之相关的原型(prototype)、类(class)和可扩展性(extensible attribute)。

6.8.1 原型属性

对象的原型属性是用来继承属性的,经常把“o的原型属性”直接叫做“o的原型”。

要检测一个对象是否是另一个对象的原型(或处于原型链中),可以使用isPrototypeOf()方法,看下面两个例子:

var p = {x:1};
var obj = Object.create(p);
p.isPrototypeOf(obj); //=> true
var d = new Date();
Date.prototype.isPrototypeOf(d);  //=>true
Object.prototype.isPrototypeOf(d) //=>true: 原型链中
6.8.2 类属性

对象的类属性(class attribute)是一个字符串,用以表示对象的类型信息。

调用对象的toString()方法,提取返回字符串的第8到倒数第2个位置之间的字符就可以获得对象的类,下面这个函数实现了这个功能:

//获取类属性的函数
function classof(o){
    if(o===null) return "Null";
    if(o===undefined) return "Undefined";
    return Object.prototype.toString.call(o).slice(8,-1);
}

//---测试这个函数,进行类属性的获取---
classof(null)       //=> "Null"
classof(false)      //=> "Boolean"
classof(new Date()) //=> "Date"

function f(){}      //定义一个自定义构造函数
classof(f)          //=> "Function"
classof(new f())    //=> "Object"
6.8.3 可扩展性

对象的可扩展性用以表示是否可以给对象添加新属性。

方法作用方法返回备注
Object.preventExtensions()将对象转换为不可扩展传入对象一旦将对象转换为不可扩展,将无法将其转换回可扩展
Object.seal()将对象转换为不可扩展,且所有自有属性不可配置同上已经封闭(sealed)的对象不能解封。不能给对象添加新属性,已有属性不能删除和配置,除了已有的可写属性可以设置。
Object.freeze()冻结对象,对象不可以扩展,自有属性不可配置且为只读同上如果对象存取器属性具有setter方法,则该属性赋值依然可用
Object.isExtensible()检测对象是否可扩展布尔型在ECMAScript5中,所有内置对象和自定义对象都是可以扩展的。
Object.isSealed()检测对象是否封闭同上-
Object.isFrozen()检测对象是否冻结同上-
var obj={x:1};
Object.isExtensible(obj);      //=> true

Object.preventExtensions(obj); //=> {x: 1}
Object.isExtensible(obj);      //=> false
obj.y=2;
obj.y                          //=> undefined: 说明不可扩展 

delete obj.x;
obj.x                          //=> undefined: 属性可以被删除
var obj = Object.defineProperties({},{
    x:{value:1, writable:true, configurable: true},
    y:{value:2, writable:false, configurable: true},
});


//6.7.2中讲到,不可读的属性可以通过配置进行修改,而封锁之后不可修改了
Object.defineProperty(obj,"y",{value: 200}); //=> {x: 1, y: 200}
Object.seal(obj);                            //=> {x: 1, y: 200}: 封锁
Object.defineProperty(obj,"y",{value: 300}); //=> Uncaught TypeError

Object.defineProperty(obj,"x",{value: 100}); //=> {x: 100, y: 200}: 由于x是可写属性,依旧可以修改

delete obj.x                                 //=> false: 不可删除

Object.isSealed(obj);                        //=> true: 已经封锁
var obj = Object.defineProperties({},{
    x:{value:1, writable:true, configurable: true},
    y:{value:2, writable:false, configurable: true},
});

Object.freeze(obj);                          //=> {x: 1, y: 2}: 冻结
Object.defineProperty(obj,"x",{value: 100}); //=> Uncaught TypeError: 所有属性只读

Object.isFrozen(obj);                        //=> true: 已经冻结

6.9 序列化对象

对象序列化(serialization)是指对象字符串间相互转换。

6.9.1 认识JSON

JSON: **J**ava**S**cript **O**bject **N**otation(JavaScript对象表示法),是轻量级的文本数据交换格式。

如果一段字符串符合JSON的语法,就可以将其简称为“一段JSON”。

注意,Javascript中的对象的可以加单引号、双引号或者不加引号,而JSON必须使用双引号

关于JSON的详情,请参考:http://www.json.org.cn/

JSON在线编辑(校验、格式化):
http://www.json.org.cn/tools/JSONEditorOnline2.0/index.htm

6.9.2 JSON和JS对象的转换
函数作用
JSON.stringify()对象 –> JSON
JSON.parse()JSON –> 对象
var obj={x:1,y:2}

var myJSON = JSON.stringify(obj); 
myJSON                            //=> "{"x":1,"y":2}"

var myObj = JSON.parse(myJSON); 
myObj                             //=> {x: 1, y: 2}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第1章 JavaScript简介 1 1.1 JavaScript是什么 1 1.2 JavaScript不是什么 2 1.3 JavaScript的用处 3 1.4 JavaScript及其在Web页面中的位置 3 1.5 Ajax是什么 5 1.6 JavaScript是什么样子的 6 1.7 JavaScript及其在Web开发中承担的角色 7 1.8 JavaScript和事件 9 1.9 标准化JavaScript和W3C 11 1.9.1 JavaScript对象 12 1.9.2 文档对象模型 12 1.10 关于浏览器 13 1.10.1 JavaScript的版本 14 1.10.2 你的浏览器遵循标准吗 16 1.10.3 浏览器是否已启用JavaScript 16 1.11 JavaScript代码放在哪儿 17 1.12 验证标签 20 1.12.1 W3C验证工具 21 1.12.2 Validome验证工具 21 1.13 应知应会 22 练习 23 第2章 脚本的安装 24 2.1 HTML文档与JavaScript 24 2.2 语法细节 27 2.2.1 区分大小写问题 27 2.2.2 自由形式及保留字 27 2.2.3 语句及分号 28 2.2.4 注释 28 ... 2.2.5 〈script〉标签    2.3 生成HTML 并输出显示    2.3.1 字符串及字符串串联    2.3.2 write()及writeln()方法    2.4 关于调试    2.5 调试工具    2.5.1 Firefox    2.5.2 在Internet Explorer 8中调试    2.5.3 [removed]URL 协议    2.6 JavaScript与旧浏览器或受限的浏览器    2.7 应知应会    练习    第3章 数据类型、字面量和变量    3.1 数据类型    3.1.1 基本数据类型    3.1.2 复合数据类型    3.2 变量    3.2.1 有效变量名    3.2.2 声明和初始化变量    3.2.3 动态或宽松类型语言    3.2.4 变量作用域    3.2.5 变量的拼接    3.3 常量    3.4 要注意的bug    3.5 应知应会    练习    第4章 对话框    4.1 与用户交互    4.1.1 alert()方法    4.1.2 prompt()方法    4.1.3 confirm()方法    4.2 应知应会    练习    第5章 运算符    5.1 JavaScript运算符和表达式    5.1.1 赋值运算符    5.1.2 优先级和结合性    5.2 运算符类型    5.2.1 算术运算符    5.2.2 快捷赋值运算符    5.2.3 递增运算符和递减运算符    5.2.4 拼接运算符    5.2.5 比较运算符    5.2.6 逻辑运算符    5.2.7 条件运算符    5.2.8 位运算符    5.3 数字、字符串还是布尔值?数据类型转换    5.3.1 parseInt()函数    5.3.2 parseFloat()函数    5.3.3 eval()函数    5.4 特殊运算符    5.5 应知应会    练习    第6章 条件选择    6.1 控制结构、块及复合语句    6.2 条件    6.2.1 if/else    6.2.2 if/else if    6.2.3 switch    6.3 循环    6.3.1 while循环    6.3.2 do/while循环    6.3.3 for循环    6.3.4 for/in循环    6.3.5 使用break和continue控制循环    6.3.6 嵌套循环及标签    6.4 应知应会    练习    第7章 函数    7.1 什么是函数    7.1.1 函数声明和调用    7.1.2 返回值    7.1.3 匿名函数变量    7.1.4 闭包    7.1.5 递归    7.1.6 函数是对象    7.2 调试技巧    7.2.1 函数语法    7.2.2 使用try/catch和throw捕捉异常    7.3 应知应会    练习    第8章 对象    8.1 什么是对象    8.1.1 对象及点语法    8.1.2 使用构造函数创建对象    8.1.3 对象的属性    8.1.4 对象方法    8.2 类和用户自定义函数    8.2.1 什么是类    8.2.2 什么是this   

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值