资讯专栏INFORMATION COLUMN

JS语言核心——“对象”

chavesgu / 2970人阅读

摘要:属性特性每个属性与之相关的值可写可枚举可配置对象特性原型类扩展标记三类对象内置对象由规范定义的对象或类宿主对象由解释器所嵌入的宿主环境定义的自定义对象由运行中的代码创建的对象两类属性自有属性直接在对象中定义的属性继承属性在对象的原型对象中

属性特性(property attribute):每个属性与之相关的值:

可写(writable attribute);

可枚举(enumerable attribute);

可配置(configurable attribute);

对象特性(object attribute):

原型(prototype);

类(class);

扩展标记(extensible flag);

三类js对象:

内置对象(native object):由ECMAScript规范定义的对象或类;

宿主对象(host object):由js解释器所嵌入的宿主环境定义的;

自定义对象(user-defined object):由运行中的js代码创建的对象

两类属性:

自有属性(own property):直接在对象中定义的属性;

继承属性(inherited property):在对象的原型对象中定义的属性;

1 创建对象

三种方法:直接量;newObject.create()函数;

1.1 对象直接量

语法:

var o = {};
1.2 通过new创建对象

语法:

var o = new Object();
1.3 原型

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

1.4 Object.create()

第一个参数是这个对象的原型;第二个可选参数是对对象的属性进行进一步描述

//创建一个普通的空对象
var o = Object.create(Object.prototype);
2 属性的查询和设置

[].

2.1 作为关联数组的对象

JavaScript对象都是关联数组(字典、映射、散列等)

2.2 继承

[暂跳]

2.3 属性访问错误

当访问不存在的对象的属性就会报错,可以通过下面方法避免出错:

var book = {};
var len;
if (book.subtitle) {
    len = book.subtitle.length;
}
console.log(len); //undefined

//或者
var book = {subtitle:"toJSON"};
var len;
len = book && book.subtitle && book.subtitle.length; //&&运算符的短路行为
console.log(len); //6
//当左操作数是真值时,“&&”运算符将计算右操作数的值并将其返回作为整个表达式的计算结果
2.4 删除属性

delete运算符不能删除继承属性

3 检测属性

5种方法:

in运算符,检测自有属性和继承属性

var o = {name:"Oliver",age:18,nothing:undefined};
console.log("name" in o); //True
console.log("toString" in o); //True
console.log("nothing" in o); //True

hasOwnProperty方法,检测自有属性

var o = {name:"Oliver",age:18,nothing:undefined};
console.log(o.hasOwnProperty("toString")); //False
console.log(o.hasOwnProperty("name")); //True

propertyIsEnumerable方法,检测自有可枚举的属性

var o = {name:"Oliver",age:18,nothing:undefined};
console.log(o.propertyIsEnumerable("toString")); //False
console.log(o.propertyIsEnumerable("name")); //True

"!=="方法,检测属性是否为undefined

var o = {name:"Oliver",age:18,nothing:undefined};
console.log(o.name !== undefined); //True
console.log(o.nothing !== undefined); //False

有一种场景只能使用in运算符。in可以区分不存在的属性和存在但是值为undefined的属性:

var o = {name:"Oliver",age:18,nothing:undefined};
console.log("nothing" in o); //True
console.log(o.nothing !== undefined); //False
delete o.nothing;
console.log("nothing" in o); //False
console.log(o.nothing !== undefined); //False

需要注意的是,"!=="可以区分undefined和null

4 枚举属性

把p中的可枚举属性赋值到o中,并返回o,如果有同名属性则覆盖o中的属性

function extend (o, p) {
    for (var prop in p) {
        o[prop] = p[prop];
    }
    return o;
}

如:

var p = {name:"Oliver",age:18,nothing:undefined};
var o = {};

function extend (o, p) {
    for (var prop in p) {
        o[prop] = p[prop];
    }
    return o;
}

console.log(extend(o,p));

将p中的可枚举属性复制到o中,并返回o,如果有同名属性则不覆盖o中的属性

function merge (o, p) {
    for (var prop in p) {
        if (o.hasOwnProperty(prop)) {
            continue;
            o[prop] = p[prop];
        }
    }
    return o;
}

如:

var p = {name:"Oliver",age:18,nothing:undefined};
var o = {name:"Oli"};

function merge (o, p) {
    for (var prop in p) {
        if (o.hasOwnProperty(prop)) {
            continue;
            o[prop] = p[prop];
        }
    }
    return o;
}

console.log(merge(o,p).name); //Oli

如果o中的属性在p中没有同名属性,则从o中删除这个属性

function restrict (o, p) {
    for (var prop in o) {
        if (!(prop in p)) {
            delete o[prop];
        }
    }
    return o;
}

如:

var p = {age:18,nothing:undefined};
var o = {name:"Oli"};

function restrict (o, p) {
    for (var prop in o) {
        if (!(prop in p)) {
            delete o[prop];
        }
    }
    return o;
}

console.log(merge(o, p).name); //undefined

如果o中的属性在p中存在同名属性,则从o中删除这个属性

function subtract (o, p) {
    for (var prop in o) {
        if (prop in p) {
            delete o[prop];
        }
    }
    return o;
}

如:

var p = {name:"Oliver",age:18,nothing:undefined};
var o = {name:"Oli"};

function subtract (o, p) {
    for (var prop in o) {
        if (prop in p) {
            delete o[prop];
        }
    }
    return o;
}

console.log(subtract(o, p).name); //undefined

返回一个新对象,这个对象同时拥有o的属性和p的属性,如果有重名属性,使用p中的属性值

function union (o, p) {
    for (var prop in o) {
        if (prop in p) {
            o[prop] = p[prop]
        }
    }
    return o;
}

如:

var p = {name:"Oliver",age:18,nothing:undefined};
var o = {name:"Oli"};

function union (o, p) {
    for (var prop in o) {
        if (prop in p) {
            o[prop] = p[prop]
        }
    }
    return o;
}

console.log(union(o, p).name); //Oliver

返回一个新对象,这个对象同时拥有o的属性和p的属性,如果重名,使用o的值

function intersection (o, p) {
    for (var prop in o) {
        if (prop in p) {
            delete p[prop];
        }
    }
    return o;
}

如:

var p = {name:"Oliver",age:18,nothing:undefined};
var o = {name:"Oli"};

function intersection (o, p) {
    for (var prop in o) {
        if (prop in p) {
            delete p[prop];
        }
    }
    return o;
}

console.log(intersection(o, p).name); //Oliver

返回一个数组,这个数组包含的是o中可枚举的自有属性的名字

5 属性getter和setter

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

语法:

var o = {
    data_prop: value,/*这是普通数据属性*/
get accessor_prop(){/*这里是函数体*/},
set accessor_prop(value){/*这里是函数体*/}
};

这个定义没有使用function关键字,而是使用get和(或)set

存取器属性是可以继承的

var o = {
    n: 0,/*这是普通数据属性*/
get next(){return this.n++},
set next(n){this.n = n}
};
o.next = 10; //setter
console.log(o.next) //getter
6 属性的特性

存取器属性的四个特性:读取(get)、写入(set)、可枚举性(enumerable)和可配置性(configurable)

数据属性的四个特性:值(value)、可写性(writable)、可枚举性(enumerable)和可配置性(configurable)

获得某个对象特定属性的属性描述符

Object.getOwnPropertyDescriptor()方法:

//name数据属性
let o = {
    name: "Oliver",
    get transferName(){return this.name},
    set transferName(value){this.name = name}
};
let result = Object.getOwnPropertyDescriptor(o, "name");
console.log(result); //Object
for (let name in result) {
    console.log(name, result[name]);
}
//value Oliver
//writable True
//enumerable True
//configurable True

//transferName存取器属性
let o = {
    name: "Oliver",
    get transferName(){return this.name},
    set transferName(value){this.name = name}
};
let result = Object.getOwnPropertyDescriptor(o, "transferName");
console.log(result); //Object
for (let name in result) {
    console.log(name, result[name]);
}
//get function transferName(){return this.name} 
//set function transferName(value){this.name = name} 
//enumerable True
//configurable True

设置属性的特性

Object.defineProperty()方法:

let o = {
    name: "Oliver",
    get transferName(){return this.name},
    set transferName(value){this.name = name}
};
let result = Object.getOwnPropertyDescriptor(o, "name");
console.log(result); //Object
for (let name in result) {
    console.log(name, result[name]);
}
//value Oliver
//writable True
//enumerable True
//configurable True
Object.defineProperty(o, "name", {
    value: "Oli",
    writable: false,
    enumerable: false,
    configurable: false
});
let result1 = Object.getOwnPropertyDescriptor(o, "name");
console.log(result1); //Object
for (let name in result1) {
    console.log(name, result1[name]);
}
//value Oli 
//writable False 
//enumerable False 
//configurable False 

该方法不能修改继承属性

设置多个属性特性

Object.defineProperties()方法:

语法:Object.defineProperties(Object, props)

var obj = {};
Object.defineProperties(obj, {
    x: {value: 1, writable: false, enumerable: true, configurable: false},
    y: {get: function(){return this.x}, enumerable: true, configurable: false}
});
console.log(obj.y); //1
console.log(obj.x); //1
obj.x = 2;
console.log(obj.x); //严格模式下报错

老式API

在ES5之前,需要用到

__lookupGetter()__

__lookupSetter()__

__defineGetter()__

__defineSetter()__

7 对象的三个属性

原型(prototype)

类(class)

可扩展性(extensible)

7.1 原型属性

对象的原型属性是用来继承属性的

var obj = {};
console.log(obj.constructor); //function Object(){ [native code] }
console.log(obj.__proto__); //Object
console.log(Object); //function Object(){ [native code] }
console.log(Object.prototype); //Object
console.log(Object.prototype.isPrototypeOf(obj)); //True

检测一个对象是否是另一个对象的原型

isPrototypeOf()方法

var obj = {};
var anotherObj = Object.create(obj);
console.log(Object.prototype.isPrototypeOf(obj)); //True
console.log(obj.isPrototypeOf(anotherObj)); //True
7.2 类属性

是一个字符串,用以表示对象的类型信息,默认的toString()方法很有可能被修改,所以应该使用下面的classof函数:

查询类

使用classof()函数:

function classof (o) {
    if (o === null) {
        return "Null";
    }
    if (o === undefined) {
        return "Undefined";
    }
    return Object.prototype.toString.call(o).slice(8, -1);
}

例如:

console.log(classof(obj)); //Object
console.log(classof(Number)); //Function
console.log(classof(123)); //Number
7.3 可扩展性

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

设置为不可扩展,检测是否不可扩展

Object.preventExtensions()设置为对象不可扩展

Object.isExtensible()检测是否可扩展

var obj = {
    name: "Oliver"
};
Object.preventExtensions(obj);
obj.name = "Oli"; //可修改属性的值
delete obj.name; //可配置属性
obj.age = 18; //不可扩展 严格模式下报错

设置为不可扩展且不可配置,检测是否不可扩展且不可配置

Object.seal()

Object.isSealed()

var obj = {
    name: "Oliver"
};
Object.seal(obj);
obj.name = "Oli"; //可修改属性的值
delete obj.name; //不可配置属性 严格模式下报错
obj.age = 18; //不可扩展 严格模式下报错

设置为不可扩展、不可配置且所有数据属性设置为只读(setter不受影响),以及检测方法

Object.freeze()

Object.isFrozen()

var obj = {
    name: "Oliver",
    anotherObj: {
        name: "Oliver"
    },
    set setName (value) {
        this.name = value;
    }
};
Object.freeze(obj);
obj.anotherObj.name = "Oli"; //可以修改属性值为对象的子对象的属性
obj.setName = "Oli"; //不可修改setter属性的值
obj.name = "Oli"; //不可修改属性的值
delete obj.name; //不可配置属性 严格模式下报错
obj.age = 18; //不可扩展 严格模式下报错
8 序列化对象

对象序列化(serialization):将对象的状态转换为字符串,或将字符串还原成对象;

JSON.stringify()

JSON.parse()

JSON(JavaScript Object Notation):JavaScript对象表示法;

var date = new Date();
console.log(date.toString()); //与JSON.stringify()的返回值不同
console.log(date.toJSON()); //与JSON.stringify()的返回值一样
9 对象方法

toString方法

toLocaleString方法

toJSON方法(严格意义上不算对象原型的方法)

valueOf方法(用在需要将它转换成某种原始值而非字符串的时候)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79051.html

相关文章

  • JavaScript 简介

    摘要:简介原文链接简称是一种轻量级,解释型的编程语言,其函数是一等公民。标准的目标是让任何一种程序设计语言能操控使用任何一种标记语言编写出的任何一份文档。核心规定了如何映射基于的文档结构,以便简化对文档的任意部分的访问和操作。 JavaScript 简介 原文链接 JavaScript ( 简称:JS ) 是一种 轻量级,解释型 的编程语言,其函数是一等公民。众所周知,它是用于网页开发的脚...

    URLOS 评论0 收藏0
  • 33 个 js 核心概念(二):数据类型

    摘要:举个例子在上面的例子可以看到,我们声明是一个数字,但是我们在之后将的值又改成了字符串和布尔值后面会讲这些类型。基本类型字符串表示一个字符串,如。因此,我们可以写一个函数,用来精确检测类型。 showImg(https://segmentfault.com/img/remote/1460000017309509?w=850&h=572); 定义 1. 什么是数据类型? 数据类型,就是将...

    QiShare 评论0 收藏0
  • task0002(一)- JavaScript数据类型及语言基础

    摘要:不过让流行起来的原因应该是是目前所有主流浏览器上唯一支持的脚本语言。经过测试,数字字符串布尔日期可以直接赋值,修改不会产生影响。再考虑对象类型为或者的情况。对于结果声明其类型。判断对象的类型是还是,结果类型更改。 转载自我的个人博客 欢迎大家批评指正 1. 第一个页面交互 这里最需要学习的老师的代码中,每一部分功能都由函数控制,没有创建一个全部变量。且最后有一个函数来控制执行代码...

    elarity 评论0 收藏0
  • JS面向对象之一 【概述】

    摘要:更形象的我们还可以将面向对象理解为一种宗教信仰。这就导致面向对象教的程序员们在写时就很难受。所以为了满足信仰面向对象教的需求通过构造函数的形式模拟了伪类。这个套路的核心就是类那么里没有类所以其实是通过构造函数来模拟的伪类。 JS面向对象之一 【概述】 在学习JS的面向对象之前,我们应该先自问这样几个问题: 面向对象是什么意思? 学习面向对象的核心是什么? 为什么要学习面向对象?(它的...

    JohnLui 评论0 收藏0
  • JavaScript 语言核心笔记(持续更新)

    摘要:在同一个块内,不允许用重复声明变量。中为新增了块级作用域。自带遍历器的对象有数组字符串类数组对象对象的对象等和结构对象。返回一个遍历器,使遍历数组的键值对键名键值。 目录 1.语法 2.类型、值和变量 3.表达式和运算符 4.语句 5.数组 6.对象 7.函数 8.全局属性和方法 9.词法作用域、作用域链、闭包 10.原型链、继承机制 11.this的理解 12.ES5新特性 13.E...

    suosuopuo 评论0 收藏0
  • JS语言核心——“表达式和运算符”

    摘要:原始表达式直接量保留字变量原始表达式表达式的最小单位表达式中的短语,解释器会将其计算为一个结果对象和数据的初始化表达式对象直接量和数组直接量,它们和布尔直接量不同,它们不是原始表达式函数定义表达式函数直接量也不是原始表达式属性访问表达式语法 1 原始表达式 直接量、保留字、变量 原始表达式(primary expression):表达式的最小单位 表达式:JavaScript中的短语...

    李增田 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<