javascript中的对象

本文深入探讨JavaScript对象的定义、类型、内置对象、属性访问、复制、属性描述符、不变性等核心概念,揭示JS对象的独特特性和高效使用技巧。

1.语法

对象可以通过两种形式定义:声明形式和构造形式

声明形式

var myObj = {
    key: value
};

构造形式

var myObj = new Object();
myObj.key = value;

2.类型

string

number

boolean

null

undefined

object

3.内置对象

String

Number

Boolean

Object

Function

Array

Date  (日期)

RegExp  (正则表达式)

Error  (异常)

var strPrimitive = "I am a string";
console.log(typeof strPrimitive);
console.log(strPrimitive instanceof String);

var strObject = new String("I am a string");
console.log(typeof strObject);
console.log(strObject instanceof String);

console.log(Object.prototype.toString.call( strObject ));
 

tips:

typeof

用于判断数据类型,返回值为6个字符串,分别为stringBooleannumberfunctionobjectundefined

instanceof

instance中文翻译为实例,因此instanceof的含义就不言而喻,判断该对象是谁的实例,同时我们也就知道instanceof是对象运算符。
这里的实例就牵扯到了对象的继承,它的判断就是根据原型链进行搜寻,在对象obj1的原型链上如果存在另一个对象obj2的原型属性,那么表达式(obj1 instanceof obj2)返回值为true;否则返回false

strPrimitive为原始值,对象字面量,js中在必要的时候字面量会转换成对象

null,undefined只有文字形式(大括号的那种创建),Date只有构造形式(new)

Object,Array,Function,RegExp无论是哪种形式,它们都是对象,而不是字面量

3.内容

var myObject = {
    a: 2
};

myObject.a;

myObject["a"];

两种访问方式都可以访问到对应的值, 前者是属性访问(必须符合标识符规范),后者是键访问(utf-8、unicode)

在对象中,属性名始终都是字符串,即使不是字符串也会转换成字符串

1.可计算属性名

var prefix = "foo";

var myObject = {
    [prefix + "bar"]:"hello",
    [prefix + "baz"]:"world"
};

myObject["foobar"];  //hello
myObject["foobaz"]; //world

prefix + 字符串成为了属性名的名字

2.属性与方法

每次访问对象的属性就只能是属性访问,即使返回的是一个函数,也并不是方法,只是一个普通的函数

3.数组

js中的数组与其他语言的数组略有些区别,

var myArray = ["foo",42,"bar"];
myArray.baz = "baz";
myArray.length = 3; //3
myArray.baz; //"baz"

数组可以添加属性名,而且数组的长度并不会变化,但并不推荐这么用数组,如果你的属性名看起来像数组的话就将直接修改数组里面的值

4.复制对象

浅拷贝: 浅拷贝出来的对象和原来的对象在同一空间,只是引用

深拷贝:重新开辟一片空间,两个对象并不公用同一空间

es6中定义了Object.assign来实现浅复制

var newObj = Object.assign({},myObject);

第一个参数是目标对象,后面可以跟一个或多个源对象

5.属性描述符

从es5开始,所有的属性都具备了属性描述符

var myObject = {
    a:2
};

Object.getOwnPropertyDescriptor( myObject,"a",{
    value: 2,
    writable: true,
    enumerable: true,
    configurable: true   
)

在创建普通属性时会使用默认值,我们也可以使用Object.defineProperty来添加新属性或修改已有的属性

将可写置为false,则不能修改对象的属性值,严格模式下会报错typeError

var myObject = {};
Object.defineProperty( myObject,"a", {
    value: 2,
    writable: false,
    configurable: true,
    enumerable: true
});

myObject.a = 3;
myObject.a //2

将configurable修改为false之后则不能对属性描述符进行修改,进行修改则会报错,无论是在严格模式下还是非严格模式下都会报错,所以configurable修改为false是一个单向操作无法修改,甚至delete操作都会失败,因为delete是删除对象的属性来对元素进行删除的,而将configurable修改为false就无法进行删除了

 

最后,enumerable是控制对象的属性能不能出现在属性枚举中,比如for ... in 循环

 

6.不变性

1.对象常量:将writable和configurable全部设置为false,不可修改或删除

2.禁止扩展: Object.preventExtensions(..);

3.密封:Object.seal()不能做任何的修改,也无法重新配置或删除现有的属性。这个方法实际上会在一个现有对象调用Object.preventExtensions并把现有属性标记为configurable:false

4.冻结:Object.freeze(),这个方法实际上是调用Object.seal()并把数据访问属性标记为writable:false

7.[[Get]]

 

var myObject = {
    a:2
};

myObject.a;

myObject.a在myObject实际上实现了[[get]]操作,如果[[get]]找不到对应的属性的话,那么它们将会返回undefined

8.[[getter]],[[setter]]

var myObject = {
    get a() {
        return 2;
    }
};

Object.defineProperty(
    myObject,
    "b",
    {
        get: function() { return this.a*2;},
        enumerable: true
    }
};

myObject.a; //2

myObject.b; //4

9.存在性

var myObject = {
    a:2
};

("a" in myObject);  //true
("b" in myObject);   //false

myObject.hasOwnProperty(" a ");  //true
myObject.hasOwnProperty(" b ");    //false

in操作符会检查属性是否在对象及其[[prototype]]原型链中,hasOwnProperty(...)只会检查属性是否在myObject对象中,不会检查[[prototype]]链

propertyIsEnumerable(...)会检查给定的属性名是否直接存在于对象并且可枚举

Object.keys(...)返回一个数组,包括所有可枚举属性

Object.getOwnPropertyNames(...)会返回一个包含所有属性的数组,无论是否可枚举

4.遍历

forEach(...)会遍历数组中的所有值并忽略回调函数的返回值

every(...)会一直运行到回调函数返回false,some(...)会一直运行直到回调函数返回true

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值