js权威指南-第六章

本文深入探讨JavaScript中的对象概念,包括创建对象的各种方法、属性的操作、继承机制、属性的特性及对象的锁定等高级主题。

第六章–对象

6.1 创建对象
三种方法

6.1.1 对象直接量
    对象直接量就相当于使用键值对进行对象的属性配置,类似与 json。
var empty={};//没有任何属性的对象
var point={x:2,y=0};//两个属性
......
6.1.2 通过new 创建对象

6.1.3 原型
    所有对象直列量创建的对象都具有同一个原型对象,并且通过 js代码 Object.prototype 获得对原型对象的引用。通过关键字 new 创建出来的对象的原型就是构造函数的 prototype 属性的值。
    没有原型的对象并不多, Object.prototype 就是其中之一。

6.1.4 Object.create()
    另有一个 Object.create()的方法。他创建一个对象,其中第一个对象是这个对象的原型。他提供了第二个可选参数,用以对这个对象的属性进行进一步描述。
    这是一个静态方法。
var o1=Object.create({s:1,j:6});//o1继承了属性s和j
var o2=Object.create(null); //o2 不继承任何属性和方法,甚至不含toString ,所以不可以和 ’+‘ 运算符一起工作

例6-1:通过原型继承创建一个新对象

function inherit(p){
    if(p==null)
        throw TypeError();//p 是一个对象,但不能为空
    if(Object.create)
        return Object.create(p);//直接使用它
    var t=typeof p;//否则进行进一步检测
    if(t!=="Object"&&t!=="funcrtion")
        throw TypeError();
    function f(){};//定义一个空的构造函数
    f.prototype=p;//讲其原型设定为p
    return new f(); //使用f创建p的继承对象
}

inherit函数的其中一个用途就是防止库函数无意间修改那些不受你控制的对象。不是讲对象作为参数传递给函数,而是将他的继承对象传入。当函数读取继承对象的属性进行修改时,实际上修改的只是这个继承对象本身,而不是原始对象。

6.2 属性的查询和设置
之前说过通过点(.) 或者 方括号([ ]) 可以获取属性的值。
和查询属性一样,也可以通过相同方式为对象设置属性赋值。

book.edition=6;//未book创建一个名为 edition的属性。
boook["main title"]="ECMAScript";//"main title"属性赋值
6.2.1 作为关联数组的对象
    上文说到,下面有个js表达式的值相同
object.property;
object["property"]
第二种语法更像是数组,只是这个数组元素是通过字符串索引而不是通过数字索引。这种数组就是我们说的关联数组。js对象都是关联数组。
当通过点操作符来操作属性时,属性名必须是一个标示符。标示符必须直接出现在 js 程序中。他们不是数据类型,程序无法修改他们。
当通过[] 来访问对象属性时,属性名字通过字符串表示。字符串是js数据类型,可以再运行时修改他们,因此可以使用如下代码
var addr="";
for(i=0;i<5;i++){
    addr+=consumer["address"+i];
}
6.2.2 继承

6.2.3 属性访问错误
    属性访问并不总是返回或设置一个值。
    查询一个不存在的属性并不会报错,如果在对象o之中的自身属性或者继承属性都没有找到指定属性,则讲返回 undefined 
    但是如果查询一个不存在对象的属性就会报错。
    另外有一些属性是只读的,不能别重新赋值。但是这些操作都不会报错。比如对 object.prototype 赋值不会成功而且不会报错。

6.3 删除属性
delete 操作符可以删除对象的属性。
注意 delete 只是断开对象与属性之间的关系。而不会去操作属性中的属性。
而且delete只能删除自身的属性,不能删除继承来的属性。
当删除成功或者没有任何副作用(删除不存在的属性)会返回 true。

o={x:1};
delete o.x; //删除x 返回true
delete o.x; //x已经不存在了,返回true
delete o.toString; // toSting 是继承而来的,什么也没有做,返回 true
delete 1; //无意义
delete 不能删除那些可配置性为 false 的属性。比如通过变量声明的或者函数声明的全局变量。这些情况下 delete 会返回 false
delete object.prototype;//不能删除,该属性不可配置
var x=1;//声明一个全局变量
delete this.x;//不能删除这个属性
function f(){};//声明一个全局函数
delete this.f;//也不能删除全局函数

6.4 检测属性
js可以视为属性的集。我们可以使用 in操作符,hasOwnProperty,propertyIsEnumerable 方法检测。
in 操作符左边是属性名,右边是一个对象。如果这个对象的自有属性或者继承属性包含这个属性,就返回 true。

var o={x:1};
"x" in o;//true
"y" in o;//false
"toString" in o;//true
对象的 hasOwnProperty 方法用来检测给定的名字是否是对象的自有属性。对于继承而来的属性会返回 false
var o={x:1};
o.hasOwnProperty("x");//true
o.hasOwnProperty("y");//false
o.hasOwnProperty("toString");//false
propertyIsEnumerable() 只有在检测到是自有属性而且是可枚举的才能返回 true
var o=inherit({y:2});
o.x=1;
o.propertyIsEnumerable("x");//true
o.propertyIsEnumerable("y");//false
o.propertyIsEnumerable("toString");//false .可以枚举

除了in操作符之外,还有一种更加简洁的方法来判断属性是否是 undefined。

var o={x:2};
o.x!==undefined;//true
o.y!==undefined;//false,没有这个属性
0.toString!==undefined;//true

值得注意的是 in可以区分属性存在但是值为 undefined的属性。!==操作符可能检测存在但是其值为 undefined的属性

6.5 枚举属性

6.6 属性 setter 和 gettter
定义储存器属性最简单的是使用对象直接量语法的一种扩展。

举个栗子:

var p={
    x:1.0,
    y:2.0,
    get r(){
        return Math.sqrt(this.x*this.x+this.y*this.y);
    },
    set r(newvalue){
        var oldvalue=Math.sqrt(this.x*this.x+this.y*this.y);
        var ratio=newvalue/oldvaluxe;
        this.x*=ratio;
        this.y*=ratio;
    },
    get theta(){
        return Math.atan2(this.y,this.x);
    }
};
这里函数定义没有使用 function 的关键字,而是使用 get set。而且函数自检没有使用分好分开,而是使用逗号分隔。属性也是如此。

6.7 属性的特性
可以认为一个属性包括四个特性,读取,写入,可枚举,可配置。
通过调用 Object.getOwnPropertyDescriptor() 获取某个对象特定属性的属性描述符。

//返回 {value:2,writable:true,enumerable:true,configrable:true}
Object.getOwnPropertyDescriptor({x:2,"x"});
//返回 {get:/*fun*/,set:undfined,enumerable:true,configurable:true}
Object.getOwnPropertyDescriptor(random,"octet");
//对于不存在或是继承而来的属性,将返回 undefined
Object.getOwnPropertyDescriptor({},"x");
Object.getOwnPropertyDescriptor({},"toString");
想要设置属性的特性,或者想让新建舒心具有某种特性,则需要调用 Object.defineproperty(),传入想要修改的对象、要创建或者修改的属性的名称以及属性描述符对象
var o={};
//添加不可枚举的数据属性,并赋值为1
Object.defineProperty(o,"x",{value:1,writable:true,enumerable:false,configurable:true});
//修改为只读
Object.defineProperty(o,"x",{writable:false});
//操作失败但是不会报错
o.x=2;
  • 如果对象是不可扩展的,那么可以编辑已有的自由属性,但是不能给他添加新属性
  • 如果属性时不可配置的,那么不能修改它的可配置性和可枚举性。
  • 如果存储器属性是不可配置的,则不能修改其 getter setter 方法,也不能将其转换成数据属性
  • 如果数据属性是不可配置的,则不能将它转化为存储器属性
  • 如果数据属性是不可配置的,则不能将他的可写性从false修改为true,但是可以从 true修改为 false
  • 如果数据属性是不可配置的且不可写的,则不能修改他的值。然而可配置的但是不可写的值可以修改。
//给Object.propertype 添加一个不可枚举的extend方法
//这个方法继承自调用他的对象,将作为参数传入的对象的属性一一复制
//除了值之外,也复制属性的所有特性,除非在目标对象中存在同名的属性,
//参数对象的所有自有对象(包括不可枚举的属性),也会一一复制
 Object.defineProperty(Object.property,"extend",{
    writable:true,//定义 Object.prototype.extend
    enumerable:false,//定义不可枚举
    configuration:true,
    value: function(o){
        //得到所有的自有属性,包括不可枚举属性
        var names=Object.getOwnPropertyNames(o);
        for(var i=0;i<names.length;i++){
            //如果属性已经存在 跳过
            if(names[i] in this) continue;
            //得到o中的属性的描述符
            var desc=Object.getOwnPropertyDescriptor(o,names[i]);
            //用他给this创建一个属性
            Object.defineProperty(this,names[i],desc);
        }

    }
});

6.8 对象的三个属性
6.8.1 原型属性
6.8.2 类属性
对象的类属性是一个字符串,用以表示对象的类型信息。
默认的 toString 方法返回如下格式字符串:
[object class]
所以想要获得对象的类,可以调用对象的 toString 方法。然后提取仪返回字符串的第8个字符到倒数第二个位置之间的字符。
classof() 函数可以返回传递给他的任意对象的类

function classof(o){
    if(o=null) return "Null";
    if(o=undefined) return "Undefined";
    return Object.prototype.toString.call(o).slice(8,-1);
}
6.8.3 可扩展性
    对象的可扩展性用以表示是否可以对对象添加新属性。
    可扩展性的目的是将对象锁定,以避免外界的干扰。
    Object.seal() 和 Object.preventExtensions() 类似。除了给对象位置为不可扩展之外,还可以将对象的所有自身属性都设置为不可配置的。也就是说不能给这个对象添加新对象,而且他已有的属性也不可以删除或配置,不过可写属性依然可以设置。注意对于那些已经封闭起来的对象是不能解封的,可以使用 Object.isSealed()来检测对象是否封闭。
    Object.freeze() 将更严格地锁定对象,除了将对象设置为不可扩展和将其属性设置为不可配置之外,还可以将它自由属性设置为只读的。使用 Object.isFrozen() 查询对象是否冻结。
var o=Object.seal(Object.create(Object.freeze({x:1}),{}));
前言1   第1章 JavaScript概述5   1.1 JavaScript语言核心8   1.2 客户端JavaScript12   第一部分 JavaScript 语言核心   第2章 词法结构25   2.1 字符集25   2.2 注释27   2.3 直接量27   2.4 标识符和保留字28   2.5 可选的分号30   第3章 类型、值和变量32   3.1 数字34   3.2 文本38   3.3 布尔值43   3.4 null和undefined44   3.5 全局对象45   3.6 包装对象46   3.7 不可变的原始值和可变的对象引用47   3.8 类型转换48   3.9 变量声明55   3.10 变量作用域56   第4章 表达式和运算符60   4.1 原始表达式60   4.2 对象和数组的初始化表达式61   4.3 函数定义表达式62   4.4 属性访问表达式63   4.5 调用表达式64   4.6 对象创建表达式64   4.7 运算符概述65   4.8 算术表达式69   4.9 关系表达式74   4.10 逻辑表达式79   4.11 赋值表达式81   4.12 表达式计算83   4.13 其他运算符86   第5章 语句91   5.1 表达式语句92   5.2 复合语句和空语句92   5.3 声明语句94   5.4 条件语句96   5.5 循环101   5.6 跳转106   5.7 其他语句类型113   5.8 JavaScript语句小结116   第6章 对象118   6.1 创建对象120   6.2 属性的查询和设置123   6.3 删除属性127   6.4 检测属性128   6.5 枚举属性130   6.6 属性getter和setter132   6.7 属性的特性134   6.8 对象的三个属性138   6.9 序列化对象141   6.10 对象方法142   第7章 数组144   7.1 创建数组 144   7.2 数组元素的读和写145   7.3 稀疏数组147   7.4 数组长度148   7.5 数组元素的添加和删除149   7.6 数组遍历149   7.7 多维数组151   7.8 数组方法152   7.9 ECMAScript 5中的数组方法 156   7.10 数组类型160   7.11 类数组对象161   7.12 作为数组的字符串163   第8章 函数165   8.1 函数定义166   8.2 函数调用168   8.3 函数的实参和形参173   8.4 作为值的函数178   8.5 作为命名空间的函数181   8.6 闭包182   8.7 函数属性、方法和构造函数188   8.8 函数式编程194   第9章 类和模块201   9.1 类和原型202   9.2 类和构造函数203   9.3 JavaScript中Java式的类继承207   9.4 类的扩充210   9.5 类和类型212   9.6 JavaScript中的面向对象技术217   9.7 子类230   9.8 ECMAScript 5 中的类239   9.9 模块248   第10章 正则表达式的模式匹配253   10.1 正则表达式的定义253   10.2 用于模式匹配的String方法261   10.3 RegExp对象263   第11章 JavaScript的子集和扩展267   11.1 JavaScript的子集268   11.2 常量和局部变量271   11.3 解构赋值274   11.4 迭代276   11.5 函数简写285   11.6 多catch 从句285   11.7 E4X: ECMAScript for XML286   第12章 服务器端JavaScript290   12.1 用Rhino脚本化Java291   12.2 用Node实现异步I/O297   第二部分 客户端JavaScript   第13章 Web浏览器中的JavaScript309   13.1 客户端JavaScript309   13.2 在HTML里嵌入JavaScript313   13.3 JavaScript程序的执行319   13.4 兼容性和互用性326   13.5 可访问性333   13.6 安全性334   13.7 客户端框架339   第14章 Window对象341   14.1 计时器342   14.2 浏览器定位和导航343   14.3 浏览历史345   14.4 浏览器和屏幕信息346   14.5 对话框348   14.6 错误处理351   14.7 作为Window对象属性的文档元素351   14.8 多窗口和窗体353   第15章 脚本化文档361   15.1 DOM概览362   15.2 选取文档元素364   15.3 文档结构和遍历371   15.4 属性375   15.5 元素的内容378   15.6 创建、插入和删除节点382   15.7 例子:生成目录表387   15.8 文档和元素的几何形状和滚动389   15.9 HTML表单396   15.10 其他文档特性404   第16章 脚本化CSS410   16.1 CSS概览411   16.2 重要的CSS属性416   16.3 脚本化内联样式427   16.4 查询计算出的样式431   16.5 脚本化CSS类433   16.6 脚本化样式表436   第17章 事件处理440   17.1 事件类型442   17.2 注册事件处理程序451   17.3 事件处理程序的调用454   17.4 文档加载事件459   17.5 鼠标事件461   17.6 鼠标滚轮事件465   17.7 拖放事件468   17.8 文本事件475   17.9 键盘事件478   第18章 脚本化HTTP484   18.1 使用XMLHttpRequest487   18.2 借助
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值