ES6 对象及拓展

一、对象与类

对象(object)是 JavaScript 最重要的数据结构

是一种数据类型,是具有相同特性(数据元素)和行为(功能)的对象的抽象。

1. 类和对象的区别
  • 类实例化的结果就是对象,类描述了一组有相同特性(属性)和相同行为的对象。
  • 类是对象的模板
//定义类
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    sayName() {
        console.log(this.name)
    }
}

let person1 = new Person("张三", 18);
person1.sayName();
let person2 = new Person("李四", 20);
2. 对象定义(声明)的两种方式

2.1 字面量的方式进行定义

var  obj = {
    name: "Tom ",
    sex: " man",
    age:19,
    run:function(){
        console.log("一天跑一公里");
    }
}

2.2 使用 new Object() 进行定义

var obj = new  Object();
//定义属性
obj.name = "Tom ";
obj.sex = " man";
obj.age = 19;
//定义方法
obj.run = function(){
    console.log("一天跑一公里");
}

二、创建对象的方式

1. 工厂模式
  • 使用简单的函数创建对象,为对象添加属性和方法,然后返回对象
// Class 模板
    function  Person(name,sex,age){
        var  obj = {};
        obj.name = name;
        obj.sex = sex;
        obj.age = age;
        obj.run = function(){
            console.log("每天坚持跑步");
        }
        return obj;
    }
    // 实例化
    var  person1 = Person("Tom","sex",19);
    //操作
    person1.run();  //  输出结果:每天坚持跑步

工厂模式的优缺点:

优点:
1、 在工厂模式中,用户只需要知道所要生产的具体东西,无须关心具体的创建过程,甚至不需要具体产品类的类名。
2、 在系统增加新的产品时,我们只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何修改,很好地符合了“开闭原则”。
缺点:
1、 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

2. 构造函数模式(new)
  • 创建自定义引用类型,可以像创建内置对象实例一样使用new操作符,这种方法的缺点是,构造函数的每个成员都无法复用,每次创建出的对象都只有私有变量和私有方法,不能实现共用
//构造函数(这里就创建了一个Class模板)
    function Person(name,sex,age){
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.run = function(){
            console.log("每天坚持跑步");
        }
    }
 // 实例化 ( new Object())
    var person1 = new Person("Tom","man",19);
 //操作
    person1.run();// 每天坚持跑步


//改造构造函数,把方法抽出来,定义成公共方法
// 构造全局的对象
var  action = {
    run:function(){
        console.log("每天坚持跑步");
    }
}
//构造函数
function Person(name,sex,age){
    ...
    this.run = action.run;
}
//实例化
var person1 = new Person("Tom","man",19);
person1.run();

使用new操作符实例化类时,相当于使用new调用其的构造函数。构造流程图如下:

  1. 创建一个空对象,作为将要返回的对象实例。
  2. 将这个空对象的原型,指向构造函数的prototype属性。
  3. 将这个空对象赋值给函数内部的this关键字。
  4. 开始执行构造函数内部的代码。(完成赋值等操作)
  5. 最后返回这个对象。
3. 原型模式
  • 使用构造函数的prototype属性来指定共享的属性和方法,即使用构造函数定义实例属性,使用原型定义共享的属性和方法
//构造函数
function Person(name,sex,age){
    this.name = name;
    this.sex = sex;
    this.age = age;
}
//使用原型对象   Object.prototype
Person.prototype.run = function() {
    console.log("每天坚持跑步");
}
//实例化
var person1 = new  Person("Tom","man",19);
person1.run();//  每天坚持跑步

三、对象的方法

JS对象方法 作用
Object.defineProperty(obj, prop,descriptor) 定义/修改一个对象中的属性
Object.defineProperties(obj.props) 在一个对象上定义新的属性或修改现有属性,并返回该对象。
Object.getOwnPropertyDescriptor(obj,prop) 获取对象中的一个属性描述
Object.freeze(obj) 冻结一个对象,再也不能被修改
Object.isFrozen(obj) 返回布尔值,判断对象是否被冻结
Object.getOwnPropertyNames(obj) 返回指定对象所有属性,同时也包括不可枚举属性组成的数组(除了Symbol属性)
Object.getOwnPropertySymbols(obj) 返回一个给定对象自身的所有Symbol属性的数组
Object.isExtensible(obj) 判断对象是否具备可扩展性,返回布尔值
Object.create(obj,propertiesObject)**** 创建一个新对象,使用现有对象来提供新创建对象的proto
Object.isSealed(obj) 返回boolean, 判断对象是否为封闭对象
十九、Object.Seal(obj) 封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置
ES6新增的对象方法
Object.is(Value1 , Value2) 判断两个值是否为"相同的值"
Object.assign(target, source1, source2) 用于对象合并,将源对象(source)所有可枚举属性,复制到目标对象(target)
Object.getOwnPropertyDescriptors(obj) 获取目标对象中的所有属性描述
Object.setPrototypeOf(obj,property) 设置一个指定的对象的原型对象
Object.getPrototypeOf(obj) 返回指定对象的原型对象
Object.keys(obj) 获取一个对象中所有的键名key (除了不可枚举属性和Symbol属性)
Object.values(obj) 获取一个对象中所有的键值value(除了不可枚举属性和Symbol属性)
Object.entries(obj) 获取一个对象中所有的键值对(key和value)
Object.fromEntries(obj) 用于将一个键值对数组转为对象

四、判断对象类型

1. typeof
  • typeof 常用来判断基本数据类型,无法做到准确的判断对象类型,返回值字符串
function sum(a,b){
  return a+b
}
var symbol1 = Symbol("a")

console.log(typeof 42); // "number"
console.log(typeof NaN); // "number"
console.log(typeof Infinity); // "number"

console.log(typeof new String(1)); // "object"
console.log(typeof new Number(1)); //"object"

console.log(typeof String(1)); // "string"
console.log(typeof Number(1)); //"number"

console.log(typeof 'string'); //"string"
console.log(typeof true);//"boolean"
console.log(typeof sum); //"function"
console.log(typeof symbol1);// "symbol"
console.log(typeof null); //"object"
console.log(typeof undefined); // "undefined"

console.log(typeof Array); 
console.log(typeof Date);
console.log(typeof Object);

console.log(typeof new Array()); 
console.log(typeof new Date());
console.log(typeof Object());

console.log(typeof Bigint);
2. instanceof
  • ES6新增,为了解决typeof 无法检查出具体对象类型,返回布尔值
  • instanceof的本质:检测构造函数(右边)的 prototype 属性是否出现在某个实例对象(左边)的原型链上
// 检查是否属于某个构造函数
function A() {
  return "A"
}
var a = new A();
console.log(a instanceof A) // true

var b = {};
console.log(b instanceof Object); //true
var c = [];
console.log(c instanceof Object); //true
console.log(c instanceof Array); //true
console.log( ({a:1}) instanceof Object) // true

let obj = Object.create(null)
console.log(obj instanceof Object) // false
// Object.create(null) 例外
//[].proto 原型是指向Array.prototype的,说明两个对象是属于同一条原型链的,返回true
3. constructor
  • 通过constructor来判断数据的类型,但是除了null、undefined,因为他们不是由对象构建。
{1:"1"}.__proto__.contructor === Object; //true
1.__proto__.contructor === Number; // true
[1].__proto__.contructor === Array; // true
4.Object.prototype.toString.call()
  • 通过Object.prototype.toString返回对象类型字符串,判断类型
  • 建议:加上call() 改变this指向,因为如果在原型上定义了toString方法,this的指向会指向为原型定义的方法,可能达不到预期目的
Object.prototype.toString.call('1') // [object String]
Object.prototype.toString.call(1) // [object Number]
Object.prototype.toString.call([1]) // [object Array]
Object.prototype.toString.call(true) // [object Boolean]
Object.prototype.toString.call(undefined) // [object Undefined]
Object.prototype.toString.call(null) // [object Null]

Object.prototype.toString.call(new Array()); // [object Array]
Object.prototype.toString.call(new Function()); // [object Function]
Object.prototype.toString.call(new Date()); // [object Date]
Object.prototype.toString.call(new Object()); // [object Object]
Object.prototype.toString.call(new RegExp()); // [object RegExp]
Object.prototype.toString.call(new Error()); // [object Error]

五、ES6对象新特性

1. 属性的简洁表示法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

  • 如果对象的属性值和属性如果发生重名,我们只写一个属性名即可,他会根据相同的属性名来获取相应的属性值;
  • 方法也可以简写。
let birth = '2000/01/01';

const Person = { //大括号里面,直接写入变量和函数,作为对象的属性和方法
  name: '张三',
  //等同于birth: birth
  birth,
  // 等同于hello: function ()...
  hello() { console.log('我的名字是', this.name); }
};

2. 属性名表达式

// 方法一  用标识符作为属性名,ES5,ES6使用字面量方式定义对象可用
obj.foo = true;
// 方法二  用表达式作为属性名,ES6使用字面量方式定义对象可用
obj['a' + 'bc'] = 123;

3. 方法的 name 属性

  • 对象中方法函数里面name隐式属性的值就是方法名
const person = {
  sayName() {
    //隐式属性name:"sayName"
    console.log('hello!');
  },
};

person.sayName.name   // "sayName"

4. 属性的可枚举性和遍历

可枚举性:对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。

属性的遍历:

遍历对象属性的方法 区别
for...in 循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)
Object.keys(obj) 返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名
Object.getOwnPropertyNames(obj) 返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名
Object.getOwnPropertySymbols(obj) 返回一个数组,包含对象自身的所有 Symbol 属性的键名
Reflect.ownKeys(obj) 返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举

5. super 关键字(做对象使用)

  • ES6 又新增了另一个类似的关键字super指向当前对象的原型对象

  • super()的另一种使用场景:作为函数使用,子类必须在constructor方法中调用super方法,继承父类的属性和方法

6. 对象的扩展运算符

  • 扩展运算符是三个点(...),将一个数组转为用逗号分隔的参数序列。
console.log(...[1, 2, 3])
// 1 2 3

console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5

[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]

7. AggregateError 错误对象

  1. AggregateError 在一个错误对象里面,封装了多个错误。如果某个单一操作,同时引发了多个错误,需要同时抛出这些错误,那么就可以抛出一个 AggregateError 错误对象,把各种错误都放在这个对象里面。

  2. AggregateError 本身是一个构造函数,用来生成 AggregateError 实例对象。

  1. AggregateError(errors[, message])的实例对象有三个属性。

    • name:错误名称,默认为“AggregateError”。

    • message:错误的提示信息。

    • errors:数组,每个成员都是一个错误对象。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354

推荐阅读更多精彩内容

  • 对象(object)是 JavaScript 最重要的数据结构。ES6 对它进行了重大升级,本章介绍数据结构本身的...
    硅谷干货阅读 220评论 0 0
  • 1.属性的简洁表示法 允许直接写入变量和函数 上面代码表明,ES6 允许在对象之中,直接写变量。这时,属性名为变量...
    雨飞飞雨阅读 1,135评论 0 3
  • 属性的简洁表示法 ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。 上面代...
    wu0228阅读 336评论 0 1
  • 一、属性的简介表示法 ES6允许直接写入变量和函数作为对象的属性和方法。允许在对象中只写属性名,不写属性值。这时,...
    了凡和纤风阅读 338评论 0 0
  • 属性的简洁表示法 ES6允许直接写入变量和函数,作为对象的属性和方法。 上面代码表明,ES6允许在对象之中,直接写...
    oWSQo阅读 509评论 0 0