JavaScript对象详细介绍

发布于:2023-01-22 ⋅ 阅读:(480) ⋅ 点赞:(0)

一、对象的创建

1、字面量模式

var obj = {
  name:"叶子yes",
  age:18,
  sayName:function(){
    console.log("my name is ",this.name);
  }
}

2、构造函数模式

var obj = new Object();
obj.name = "叶子yes";
obj.age = 18;
obj.sayName = function(){
  console.log("my name is",this.name);
}

二、对象的访问

都以这个对象为例:

var obj = {
  name:"叶子yes",
  age:18,
  sayName:function(){
    console.log("my name is ",this.name);
  }
}

1、访问属性

1.1 点访问

obj.name

1.2 中括号访问

obj['name']  //中括号里面要写字符串

2、访问方法

obj.sayName; //返回函数体
obj.sayName();  //执行函数

在这里插入图片描述

3、遍历对象属性

使用for...in循环

for(var key in obj){
  console.log(key + ':' + obj[key])
}

运行结果:

name:叶子yes
age:18
sayName:function(){
    console.log("my name is ",this.name);
  }

三、删除对象属性

只能删除对象的自有属性

delete obj.name
delete obj["name"]
delete obj.sayName     //从obj对象中删除sayName属性

四、新增或修改对象属性

obj.name = 'lisi' //name属性已经存在,就会修改该属性的值
obj.gender = '女' //gender属性不存在,就会新增该属性

五、对象的强制类型转换

ECMAScript中可用的3种强制类型转换如下:

Boolean(value)
​ 把给定的值转换成Boolean型

String(value)
​ 把给定的值转换成字符串

Number(value)
​ 把给定的值转换成数字(可以是整数或浮点数)

1、Object类型转换成Boolean类型

除了空引用 (null) 会转换为 false,其他都被转换为 true

var obj = {
  name:"叶子yes",
  age:18,
  sayName:function(){
    console.log("my name is ",this.name);
  }
}

console.log(Boolean(obj)); //true
console.log(Boolean(null)); //false
console.log(Boolean({})); //true

2、Object类型转换成String类型

对象使用String() 方法进行强制类型转换时,其内部会进行如下操作:
	
1.先调用对象的toString方法

2.判断该方法的返回值是否为基础数据类型(Number,String,Boolean,Undefined,Null)

3.若返回值为基础数据类型,则转换规则按照相应数据类型的转换规则对其进行转换

4.若返回值不为基础数据类型,则在该返回值的基础上继续调用valueOf方法

5.判断valueOf的返回值是否为基础数据类型

6.判断是否为基础数据类型,若是基础数据类型则进行操作3

7.若仍旧不为基础数据类型则报错
var obj = {
  name:"叶子yes",
  age:18,
  sayName:function(){
    console.log("my name is ",this.name);
  },
}
console.log(String(obj)); //[object Object]

可以重写toString方法,进行我们想要的转换:

var obj = {
  name:"叶子yes",
  age:18,
  sayName:function(){
    console.log("my name is ",this.name);
  },
  // 可以重写toString方法,进行我们想要的转换
  toString:function(){
    return this.name+"--"+this.age;
  }
}
console.log(String(obj)); //叶子yes--18

3、Object类型转换成Number类型

对象使用Number() 方法进行强制类型转换时,其内部会进行如下操作:

1.先调用对象的valueOf方法

2.判断该方法的返回值是否为基础数据类型(Number,String,Boolean,Undefined,Null)

3.若返回值为基础数据类型,则转换规则按照相应数据类型的转换规则对其进行转换

4.若返回值不为基础数据类型,则在该返回值的基础上继续调用toString方法

5.判断toString的返回值是否为基础数据类型

6.判断是否为基础数据类型,若是基础数据类型则进行操作3

7.若仍旧不为基础数据类型则报错

此外,如果我们重写了valueOf()、toString()方法:

1、如果只重写了valueOf()或者toString()方法,则调用该方法,并将返回值用Number()转换。

2、如果两个方法都重写了,则调用valueOf(),并将返回值用Number()转换。

3、如果两个方法都没有重写,则返回NaN

var obj = {
  name:"叶子yes",
  age:18,
  sayName:function(){
    console.log("my name is ",this.name);
  }
}
console.log(Number(obj)); //NaN

重写toString()方法:

var obj = {
  name:"叶子yes",
  age:18,
  sayName:function(){
    console.log("my name is ",this.name);
  },
  toString:function(){
    return true;
  }
}
console.log(Number(obj)); //1

重写toString()和valueOf() 方法:

var obj = {
  name:"叶子yes",
  age:18,
  sayName:function(){
    console.log("my name is ",this.name);
  },
  toString:function(){
    return true;
  },
  valueOf:function(){
    return '10';
  }
}
console.log(Number(obj)); //10

六、检测一个属性是否属于某个对象

1、in

检测某属性是否是某对象的自有属性或者是继承属性

如果用in判断一个属性存在,这个属性不一定是obj的,它可能是obj继承得到

var obj = {
  name:"叶子yes",
  age:18,
  sayName:function(){
    console.log("my name is ",this.name);
  }
}
//in运算符的左侧为属性名称,右侧为对象
console.log('name' in obj); //true
console.log('age' in obj);  //true
console.log('gender' in obj); //false

//如果用in判断一个属性存在,这个属性不一定是obj的,它可能是obj继承得到的,如:
console.log('toString' in obj);  //  true
//因为toString定义在object对象中,而所有对象最终都会在原型链上指向object,所以obj也拥有toString属性。

2、Object.prototype.hasOwnProperty()

检测给定的属性是否是对象的自有属性,对于继承属性将返回false

var obj = {
  name:"叶子yes",
  age:18,
  sayName:function(){
    console.log("my name is ",this.name);
  }
}
console.log(obj.hasOwnProperty('name')); //true
console.log(obj.hasOwnProperty('age'));  //true
console.log(obj.hasOwnProperty('gender')); //false
console.log(obj.hasOwnProperty('toString')); //false, 因为toString为继承属性

3、Object.prototype.propertyIsEnumerable()

propertyIsEnumerable()是hasOwnProperty()的增强版,除了是自身属性外,还要求是可枚举属性。

var obj = {
  name:"叶子yes",
  age:18,
  sayName:function(){
    console.log("my name is ",this.name);
  }
}
//定义一个属性,后面会讲
Object.defineProperty(obj,'gender',{
  // 是否可以被for...in循环遍历出来
  enumerable: false,
  // 设置该属性对应的值
  value: '女'
})
console.log(obj.gender) // '女'
console.log(obj.propertyIsEnumerable('gender')); //false
console.log(obj.propertyIsEnumerable('name')); //true
console.log(obj.propertyIsEnumerable('age'));  //true
console.log(obj.propertyIsEnumerable('toString')); //false,不可枚举

七、Object原型属性和方法

在Object的构造函数的原型对象中的属性和方法都可以被Object构造函数的实例所继承。

Object原型中的所具有的任何属性和方法也同样存在于其他对象中,任何对象继承自Object。
请添加图片描述
我们可以在打开浏览器控制台看一下:
在这里插入图片描述
然后,我们再展开constructor看一下:
在这里插入图片描述

总结:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,实例都包含一个指向原型对象的内部指针。

Object原型中常用的方法:

constructor

​ 保存用户创建当前对象的函数,与原型对象对应的构造函数

hasOwnProperty(propertyName)

​ 检查给定的属性名是否是对象的自有属性

propertyIsEnumerable(propertyName)

​ 检查给定的属性在当前对象实例中是否存在

valueOf()

​ 返回对象的字符串,数值,布尔值的表示

toLocaleString()

​ 返回对象的字符串表示,该字符串与执行环境的地区对应

toString()

​ 返回对象的字符串表示

isPrototypeOf(object)

​ 检查传入的对象的原型

a.isPrototypeOf(b) 如果a是b的原型,则返回true。如果b不是对象,或者a不是b的原型,则返回false。

var obj = {
  name:"叶子yes",
  age:18,
  sayName:function(){
    console.log("my name is ",this.name);
  }
}
// 调用原型对象中继承的方法
console.log(obj.toString()); //[object Object]
console.log(obj.__proto__.toString()); //[object Object]


// 构造函数 Object
console.log(Object);  //[Function: Object]
// 原型对象 Object.prototype
console.log(Object.prototype);  // {}
// 原型对象中的constructor属性  原型对象中的constructor属性指向构造函数
console.log(Object.prototype.constructor);  //[Function: Object]
// 实例__proto__ 指向 原型对象
console.log(obj.__proto__ === Object.prototype);  //true
// 检查传入的对象的原型
console.log(Object.prototype.isPrototypeOf(obj)); //true


// 创建Date对象
var now = new Date();
console.log(now); //2022-08-10T12:01:40.831Z
// 使用原型对象中的方法
console.log(now.toString());//Wed Aug 10 2022 20:01:40 GMT+0800 (GMT+08:00)
console.log(now.toLocaleString());//2022/8/10 下午8:01:40

八、定义属性

ECMAScript中有两种属性:数据属性、访问器属性。这两种属性用于设置属性的高级属性,例如该属性是否可以配置,是否可以读写,是否可以遍历,并且可以通setter,getter来监听数据的改变。

1、数据属性特性

数据属性,例如name属性,包含一个属性值的位置,这个位置可以读取和写入值。数据属性特性如下:

Configurable

​ 表示是否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性(属性直接定义在对象中,默认为true)。 当为false时,不能重新定义不能使用delete删除。

Enumerable

​ 表示能否通过for-in循环返回属性。(属性直接定义在对象中,默认为true)

​ Writable

​ 表示能否修改属性的值。(属性直接定义在对象中,默认为true)

​ Value

​ 包含这个属性的数据值 name:jacky

要修改属性默认的特性,必须使用ECMAScript5的 Object.defineProperty () 方法。

除了使用obj.name = 'zhangsan';添加属性的方式,我们还可以使用Object.defineProperty定义新属性或修改原有的属性。

定义属性

Object.defineProperty()

语法

Object.defineProperty(obj, prop, descriptor)

参数说明:
1、obj:必需。目标对象
2、prop:必需。需定义或修改的属性的名字
3、descriptor:必需。目标属性所拥有的特性

返回值:
传入函数的对象。即第一个参数obj;

var person = {
  name:'叶子yes'
}

// 使用Object.defineProperty来新增定义一个新的属性
Object.defineProperty(person,'age',{
  // 设置是否可以被delete删除掉
  configurable: false,
  // 是否可以被for...in循环遍历出来
  enumerable: true,
  // 是否可以修改值
  writable: false,
  // 设置该属性对应的值
  value: 18
})
console.log(person.age) //18

Object.defineProperties()

语法

Object.defineProperties(obj, props)

参数说明:
1、obj:必需。目标对象
2、props:该对象的一个或多个键值对定义了将要为对象添加或修改的属性的具体配置

返回值:
传入函数的对象。即第一个参数obj;

var person = {
  name:'叶子yes'
}

//使用 Object.defineProperties() 一次性定义多个属性
Object.defineProperties(person,{
  // 身高
  height:{
    configurable: false,
    value: 1.80
  },
  // 性别
  gender:{
    value:'女'
  }
})
console.log(person.height) //1.8
console.log(person.gender) //女

读取属性特性

Object.getOwnPropertyDescriptor()

功能
该方法返回指定对象上 一个自有属性对应的属性描述符。
语法

Object.getOwnPropertyDescriptor(obj, prop)

参数说明
1、obj: 需要查找的目标对象
2、prop: 目标对象内属性名称

var person = {
  name:'叶子yes'
}
// 读取对象的属性 Object.getOwnPropertyDescriptor()
console.log(Object.getOwnPropertyDescriptor(person, 'name'));

结果如下:
{
value: ‘叶子yes’,
writable: true,
enumerable: true,
configurable: true
}

Object. getOwnPropertyDescriptors()

功能:
所指定对象的所有自身属性的描述符,如果没有任何自身属性,则返回空对象。

语法

Object.getOwnPropertyDescriptors(obj)

参数说明
obj: 需要查找的目标对象

var person = {
  name:'叶子yes'
}

//使用 Object.defineProperties() 一次性定义多个属性
Object.defineProperties(person,{
  // 身高
  height:{
    configurable: false,
    value: 1.80
  },
  // 性别
  gender:{
    value:'女'
  }
})
// 读取对象的属性 Object.getOwnPropertyDescriptors()
console.log(Object.getOwnPropertyDescriptors(person));

结果如下:
{
name: {
value: ‘叶子yes’,
writable: true,
enumerable: true,
configurable: true
},
height: {
value: 1.8,
writable: false,
enumerable: false,
configurable: false
},
gender: {
value: ‘女’,
writable: false,
enumerable: false,
configurable: false
}
}

2、访问器属性特性

访问器属性:这个属性不包含数据值包含的是一对get和set方法,在读写访问器属性时,就是通过这两个方法来进行操作处理的。

访问器属性包含的四个特性:

Configurable

​ 表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或能否把属性修改为访问器属性,默认为false

Enumerable

​ 表示能否通过for-in循环返回属性,默认为false

Get

​ 在读取属性时调用的函数,默认值为undefined

Set

​ 在写入属性时调用的函数,默认值为undefined

​ 这里要注意下,访问器属性不能直接定义,要通过Object.defineProperty()这个方法来定义。

// 创建一个对象
var person = {
  // 内部属性(这里只是模拟一下)
  _birthday: 2000,
  age: 1
}
// 新增一个访问器属性
Object.defineProperty(person,'birthday',{
  get:function () {
    return this._birthday
  },
  set:function(newValue){
    if (newValue !== this._birthday) {
      this._birthday = newValue
      this.age++
    }
  }
})
// person.birthday get操作 通过点语法获取一个属性的值
person.birthday = 2001
console.log(person.age); //2

由此可以联想到数据的双向绑定:

在一个对象(person)中设置一个私有属性(_birthday:开头下划线代表私有属性),再为这个对象设置访问器属性birthday(本身还未在对象中定义),当person.birthday进行修改时触发set函数,通过这个函数可以进行数据的操作,比如数据的判断赋值等一系列操作,从而实现数据的双向绑定。这个原理是vue的本质原理。vue是数据驱动框架,当数据发生改变的时候,视图自动更新。
使用js实现双向数据绑定:https://blog.csdn.net/LQ313131/article/details/126276260

九、对象序列化

对象序列化是指将对象的状态转换为字符串,也可以反序列化,将字符串还原为对象函数。
RegExp,Error对象,undefined值不能序列化和反序列化。

JSON.stringify(obj) 将对象序列化为JSON字符串,只能序列化对象可枚举的自有属性

JSON.parse(jsonStr) 反序列化

var person = {
  name:"叶子yes",
  age:18
}

// 对象转为JSON字符串
var jsonStr = JSON.stringify(person)
console.log(jsonStr, typeof jsonStr); //{"name":"叶子yes","age":18} string
// JSON字符串转对象
console.log(JSON.parse(jsonStr)); //{ name: '叶子yes', age: 18 } 

我们可以使用 JSON.stringify(obj)JSON.parse(jsonStr) 实现深拷贝:

var person = {
  name:"叶子yes",
  age:18
}
var person1 = JSON.parse(JSON.stringify(person))
person.name = 'lisi'
console.log(person1) //{ name: '叶子yes', age: 18 }
本文含有隐藏内容,请 开通VIP 后查看