Web前端高级编程学习笔记7:对象进阶

JavaScript对象的特征

JavaScript的基本数据类型,一种复合值,可看做是属性的无序集合。

  • 每个属性都是一个名/值对。
  • 属性名是字符串,因此可以把对象看成是从字符串到值的映射。

对象除了可以保持自有的属性,还可以从一个称为原型的对象继承属性。

  • 原型式继承( prototypal inheritance )是JavaScript的核心特征。

对象是动态的,可以增加或删除属性。

除了字符串、数值、true 、 false 、null和 undefined ,其他值都是对象。

对象最常见的用法是对其属性进行创建、设置、查找、删除、检测和枚举等操作。

属性值是任意JavaScript 值,或者是一个getter 或setter函数。
每个属性还有一些与之相关的值,称为“属性特征( property abttribute ) ”。

  • 可写( writable attribute ) ,表明是否可以设置属性的值。
  • 可枚举( enumerable attribute ),表明是否可以通过for/in结构返回该属性。
  • 可配置( configurable attribute ),表明是否可以删除或修改该属性。

每个对象还拥有三个相关的对象特性

  • 对象的原型( prototype ) ,指向另一个对象,该对象的属性会被当前对象继承。
  • 对象的类( class ) ,一个标识对象类型的字符串。
  • 对象的扩展标记( extensible flag ) ,指明了是否可以向该对象添加新属性。

创建对象

对象字面量

let empty={};      //无属性对象

let point={x:0,y:0};       //有属性对象

let book={
    //属性名有空格,必须以字符串表示
    "main title":"JavaScript",
    //属性名有特殊字符,必须用字符串表示
    "sub-title":"The Definitive Gruide",
    //属性名是保留字,但尽量避免
    for:"all audiences",
    //属性值可以是另一个对象
    author:{
        firstname:"David",
        lastname:"Flanagan",
    },
};

对象字面量是一个表达式,每次运算都会创建一个新的对象,其中的属性值也会重新计算。

通过new创建对象

通过new 调用构造函数( constructor )来创建并初始化一个新对象。

JavaScript语言核心中的原始类型都包含内置构造函数,如Object() 、Array() 、Date()等。

原型

每一个JavaScript对象( null除外)都和另一个对象相关联。

  • “另一个对象”就是原型对象。
  • 每一个对象都从原型继承属性。

所有通过对象字面量创建的对象都具有同一个原型对象。

通过Object.prototype获得原型对象的引用。

通过new和构造函数创建的对象的原型就是构造函数的prototype属性引用的对象。

如: new Array()对象的原型就是Array.prototype。

极少对象没有原型。

如:0bject.prototype ,它不继承任何属性。

let obj=new Object();

obj.__proto__==Object.prototype;       //true
Object.prototype.__proto__;             //null

所有内置构造函数都具有一个继承自Object.prototype的原型

如: Array.prototype的属性继承自Object.prototype 。

通过层级的原型继承形成的链接,称为“原型链”( prototype chain ) 。
ps.另一个链是作用域链
在这里插入图片描述

let a={};
a.x=1;
let b=Object.create(a);
b.y=2;
let c=Object.create(b);
c.z=3;
console.log(c.toString());          //"[object Object]"
console.log(c.x+c.y+c.z);           //6
console.log(c.x+c.y+c.z+c.d);        //NaN

原型属性不能被继承对象属性修改。

属性相关

属性访问错误

查询一个不存在的属性并不会报错,如果在对象obj自身的属性或继承的属性中均未找到属性x ,属性访问表达式obj.x返回undefined 。
但是,如果对象不存在,那么试图查询这个不存在的对象的属性就会报错。

null和undefined值都没有属性,因此查询这些值的属性会报错。

let one={}// let one={two:{three:3}};
console.log(one.two);          //undefined
console.log(one.two.three);      //报错,
let one={}
if(one){
    if(one.two){
        if(one.two.three){
            console.log(one.two.three)}}};           //3
let one={};
console.log(one && one.two && one.two.three);    //undefined
console.log(one.two && one && one.two.three);    //undefined
console.log(one ?. two ?. three);         //undefined 代表意义同上
//    ?.   Null传导运算符

eg.
true&&100               //100
false&&100              //false
undefined&&100         //undefined
100&&undefined          //undefined
//表达式的值由不存在的值决定

删除属性

delete 运算符可以删除对象的属性。

let o={x:1}
delete o.x
//true
delete o.toString
//true
o
//{}
o.toString
//ƒ toString() { [native code] }

delete运算符只能删除自有属性,不能删除继承属性。

检测属性

判断某个属性是否存在于某个对象中,可以通过in运算符、hasOwnPreperty()和propertylsEnumerable()方法,甚至也可以仅通过属性查询。

枚举属性

for/in循环可以在循环体中遍历对象中所有可枚举的属性(包括自有属性和继承的属性),把属性名称赋值给循环变量。

对象继承的内置方法不可枚举的,但在代码中给对象添加的属性都是可枚举的。

let o=Object.create({m:10,n:20})
o.x=1
o.y=2
o.z=3
for(let p in o){
    console.log(p,o[p])
}

x 1
y 2
z 3
m 10
n 20

Tips: for/in 遍历对象属性 for/of 遍历数组

Object.keys() ,它返回一个数组,这个数组由对象中可枚举的自有属性的名称组成。

Object.keys(o)
//(3) ["x", "y", "z"]

Object.getOwnPropertyNames() ,它和Ojbect.keys()类似,只是它返回对象的所有自有属性的名称,而不仅仅是可枚举的属性。

Object.getOwnPropertyNames(o)
//(3) ["x", "y", "z"]

属性getter和setter

由getter和setter定义的属性称做“存取器属性”(accessor property),它不同于“数据属性”(data property),数据属性只有一个简单的值。

let circle={
    r:10,
    get round(){
        return 2*this.r*Math.PI;
    },
    set round(v){
        this.r=v/2/Math.PI;
    },
    get area(){
        return Math.PI*this.r**2;
    },
};
console.log(circle.round,circle.area);
//62.83185307179586 314.1592653589793

circle.round=60;
console.log(circle.r,circle.area);
//9.549296585513721 286.47889756541167
let circle1=Object.create(circle);
circle1.r=20;
console.log(circle1.round);
//125.66370614359172

circle1.round=500;
console.log(circle1.r,circle1.area);
//79.57747154594767 19894.367886486918

存取器属性实质是函数,不会重新产生,而是调用。
存取器属性和数据属性一样,同样是可以被继承的。

属性的特性

除了包含名字和值之外,属性还包含一些标识它们可写、可枚举和可配置的特性。

可以通过这些API给原型对象添加方法,并将它们设置成不可枚举的,这让它们看起来更像内置方法。
可以通过这些API给对象定义不能修改或删除的属性,借此“锁定”这个对象。

数据属性的4个特性

值(value)、可写性(writable)、可枚举性(enumerable)和可配置性(configurable) 。

存取器属性不具有值(value)特性和可写性。

它们的可写性是由setter方法存在与否决定的。
因此存取器属性的4个特性是读取(get)、写入(set)﹑可枚举性和可配置性。

通过一个名为“属性描述符”(property descriptor)的对象实现属性特性的查询和设置操作。

Object.getOwnPropertyDescriptor()可以获得某个对象特定属性的属性描述符。

console.log(Object.getOwnPropertyDescriptor(circle,"r"));

{value:9.549296585513721, writable:true, enumerable:true, configurable:true}
console.log(Object.getOwnPropertyDescriptor(circle1,"round"));

undefined

对于继承属性和不存在的属性,会返回undefined。

  • 要想设置属性的特性,或者想让新建属性具有某种特性,则需要调用object.definePeoperty(
    ),传入要修改的对象、要创建或修改的属性的名称以及属性描述符对象。
let o={}
Object.defineProperty(o,"x",{
    value:10,
    writable:true,
    enumerable:false,
    configurable:false,
});
console.log(o.x,Object.keys(o),Object.getOwnPropertyNames(o));
//10 [] [ 'x' ]

Object.defineProperty(o,"x",{enumerable:true});
console.log(Object.keys(o))
//[ 'x' ]
  • 如果要同时修改或创建多个属性,使用Object.defineProperties( ) 。

对象特性

原型属性

将对象作为参数传入Object.getPrototypeOf( )可以查询它的原型。

Tips: 也可以用 对象名.constructor.prototype 查询

要想检测一个对象是否是另一个对象的原型(或处于原型链中),使用isPrototypeOf( )方法。

let o={x:1};
let p=Object.create(o);
p.y=2;
Object.getPrototypeOf(p);
//{x: 1}
o.isPrototypeOf(p);
//true

序列化对象

对象序列化(serialization)是指将对象的状态转换为字符串,也可将字符串还原为对象,则称为反序列化
使用内置函数 JSON.stringify( )和 JSON.parse( )用来序列化和反序列化JavaScript对象。

JSON的全称是"JavaScript 0bject Notation"——JavaScript对象表示法

JSON . stringify( )只能序列化对象可枚举的自有属性。

Object构造函数的方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值