对象属性和方法

发布时间 2023-12-22 14:54:08作者: 奇迹会出现

一、什么是js 对象
对象是“键值对”的集合,是一种无序的数据的集合

二、如何声明 (创建对象)?方式有哪几种? 有什么区别
1.对象字面量 字面量的方式创建对象
2.关键字 new 内置构造函数

//字面量的方式创建对象
            var obj0 = {}
            console.log(obj0)
            var obj = {
                name: "du",
                age:100,
                location: "南昌"
            }
            console.log(obj)
            //{name: "du", age: 100, location: "南昌"}
            
            //内置构造函数
            
            var obj2 = new Object()
            console.log(obj2)
            
            obj2.name = "xiaoming"
            obj2.age = 18
            console.log(obj2)
            //{name: "xiaoming", age: 18}

三、Object.create()函数
静态方法以一个现有对象作为原型,创建一个新对象

四、对象的继承和原型、原型链?(重难点)

对于使用过基于类的语言(如 Java 或 C++)的开发者来说,JavaScript 实在是有些令人困惑——JavaScript 是动态的且没有静态类型。

当谈到继承时,JavaScript 只有一种结构:对象。每个对象(object)都有一个私有属性指向另一个名为原型(prototype)的对象。原型对象也有一个自己的原型,层层向上直到一个对象的原型为 null。根据定义,null 没有原型,并作为这个原型链(prototype chain)中的最后一个环节。可以改变原型链中的任何成员,甚至可以在运行时换出原型,因此 JavaScript 中不存在静态分派的概念。

尽管这种混杂通常被认为是 JavaScript 的弱点之一,但是原型继承模型本身实际上比类式模型更强大。例如,在原型模型的基础上构建类式模型(即的实现方式)相当简单。

尽管类现在被广泛采用并成为 JavaScript 中新的范式,但类并没有带来新的继承模式。虽然类为大部分原型的机制提供了抽象,但了解原型在底层是如何工作的仍然十分有用。

在像 { a: 1, b: 2, __proto__: c } 这样的对象字面量中,c 值(必须为 null 或另一个对象)将变成字面量所表示的对象的 [[Prototype]],而其他键(如 a 和 b)将变成对象的自有属性。这种语法读起来非常自然,因为 [[Prototype]] 只是对象的“内部属性”。

下面演示当尝试访问属性时会发生什么

const o = {
  a: 1,
  b: 2,
  // __proto__ 设置了 [[Prototype]]。它在这里被指定为另一个对象字面量。
  __proto__: {
    b: 3,
    c: 4,
  },
};

// o.[[Prototype]] 具有属性 b 和 c。
// o.[[Prototype]].[[Prototype]] 是 Object.prototype(我们会在下文解释其含义)。
// 最后,o.[[Prototype]].[[Prototype]].[[Prototype]] 是 null。
// 这是原型链的末尾,值为 null,
// 根据定义,其没有 [[Prototype]]。
// 因此,完整的原型链看起来像这样:
// { a: 1, b: 2 } ---> { b: 3, c: 4 } ---> Object.prototype ---> null

console.log(o.a); // 1
// o 上有自有属性“a”吗?有,且其值为 1。

console.log(o.b); // 2
// o 上有自有属性“b”吗?有,且其值为 2。
// 原型也有“b”属性,但其没有被访问。
// 这被称为属性遮蔽(Property Shadowing)

console.log(o.c); // 4
// o 上有自有属性“c”吗?没有,检查其原型。
// o.[[Prototype]] 上有自有属性“c”吗?有,其值为 4。

console.log(o.d); // undefined
// o 上有自有属性“d”吗?没有,检查其原型。
// o.[[Prototype]] 上有自有属性“d”吗?没有,检查其原型。
// o.[[Prototype]].[[Prototype]] 是 Object.prototype 且
// 其默认没有“d”属性,检查其原型。
// o.[[Prototype]].[[Prototype]].[[Prototype]] 为 null,停止搜索,
// 未找到该属性,返回 undefined。

给对象设置属性会创建自有属性。获取和设置行为规则的唯一例外是当它被 getter 或 setter 拦截时。

同理,你可以创建更长的原型链,并在原型链上查找一个属性。

 

const o = {
  a: 1,
  b: 2,
  // __proto__ 设置了 [[Prototype]]。它在这里被指定为另一个对象字面量。
  __proto__: {
    b: 3,
    c: 4,
    __proto__: {
      d: 5,
    },
  },
};

// { a: 1, b: 2 } ---> { b: 3, c: 4 } ---> { d: 5 } ---> Object.prototype ---> null

console.log(o.d); // 5

 

继承方法

JavaScript 并没有其他基于类的语言所定义的“方法”。在 JavaScript 中,任何函数都被可以添加到对象上作为其属性。函数的继承与其他属性的继承没有差别,包括上面的“属性遮蔽”(这种情况相当于其他语言的方法重写)。

当继承的函数被调用时,this 值指向的是当前继承的对象,而不是拥有该函数属性的原型对象。

const parent = {
  value: 2,
  method() {
    return this.value + 1;
  },
};

console.log(parent.method()); // 3
// 当调用 parent.method 时,“this”指向了 parent

// child 是一个继承了 parent 的对象
const child = {
  __proto__: parent,
};
console.log(child.method()); // 3
// 调用 child.method 时,“this”指向了 child。
// 又因为 child 继承的是 parent 的方法,
// 首先在 child 上寻找“value”属性。但由于 child 本身
// 没有名为“value”的自有属性,该属性会在
// [[Prototype]] 上被找到,即 parent.value。

child.value = 4; // 在 child,将“value”属性赋值为 4。
// 这会遮蔽 parent 上的“value”属性。
// child 对象现在看起来是这样的:
// { value: 4, __proto__: { value: 2, method: [Function] } }
console.log(child.method()); // 5
// 因为 child 现在拥有“value”属性,“this.value”现在表示
// child.value

 

 对象属性访问

const person1 = {};
person1['firstname'] = 'Mario';
person1['lastname'] = 'Rossi';

console.log(person1.firstname);
//  "Mario"

const person2 = {
  firstname: 'John',
  lastname: 'Doe',
};

console.log(person2['lastname']);
//  "Doe"

 

删除属性

const Employee = {
  firstname: 'Maria',
  lastname: 'Sanchez',
};

console.log(Employee.firstname);
// Expected output: "Maria"

delete Employee.firstname;

console.log(Employee.firstname);
// Expected output: undefined

 遍历

for...in

for...in对于新手来说有些陌生,比如以下代码,我在想这个pron这个变量值为什么就可以输出a嘞,后面查了资料,他是把obj里面每一个的值赋给了pron

 

var obj = { a: 1, b: 2, c: 3 };

for (var prop in obj) {
  console.log("obj." + prop + " = " + obj[prop]);
}

// Output:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"

 

 

Object.keys()

这个好理解,key值就是如上面代码对象里面的a、b、c、d等

 

Object.values()

这个也好理解,value值就是key值后面的值,如上面代码a后面1,1就是value值

 

Object.entries() 

他是静态方法返回一个数组,包含给定对象自有的可枚举字符串键属性的键值对

const object1 = {
  a: 'somestring',
  b: 42,
};

for (const [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`);
}

// Expected output:
// "a: somestring"
// "b: 42"

 

Object.fromEntries()

 他是静态方法将键值对列表转换为一个对象,他是这样理解的?先把entries遍历一遍,然后自己从entries里面的key和值转换成表?

const entries = new Map([
  ['foo', 'bar'],
  ['baz', 42],
]);

const obj = Object.fromEntries(entries);

console.log(obj);
// Expected output: Object { foo: "bar", baz: 42 }

 

Object.getOwnPropertyNames()

 

const object1 = {
  a: 1,
  b: 2,
  c: 3,
};

console.log(Object.getOwnPropertyNames(object1));
// Expected output: Array ["a", "b", "c"]

 

 

 

这个也好理解,就是获取全部属性值为什么的并且在后台输出出来,记住他是静态方法返回一个数组

 

Object.defineProperty()

静态方法会直接在一个对象上定义一个新属性,或修改其现有属性,并返回此对象。

 

const object1 = {};

Object.defineProperty(object1, 'property1', {
  value: 42,
  writable: false,
});

object1.property1 = 77;
// Throws an error in strict mode

console.log(object1.property1);
// Expected output: 42

 

 

Object.defineProperties()

静态方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象

const object1 = {};

Object.defineProperties(object1, {
  property1: {
    value: 42,
    writable: true,
  },
  property2: {},
});

console.log(object1.property1);
// Expected output: 42

 

JSON.stringify()

将一个 JavaScript 对象或值转换为 JSON 字符串,如果指定了一个 replacer 函数,则可以选择性地替换值,或者指定的 replacer 是数组,则可选择性地仅包含数组指定的属性

console.log(JSON.stringify({ x: 5, y: 6 }));
// Expected output: '{"x":5,"y":6}'

console.log(
  JSON.stringify([new Number(3), new String('false'), new Boolean(false)]),
);
// Expected output: '[3,"false",false]'

console.log(JSON.stringify({ x: [10, undefined, function () {}, Symbol('')] }));
// Expected output: '{"x":[10,null,null,null]}'

console.log(JSON.stringify(new Date(2006, 0, 2, 15, 4, 5)));
// Expected output: '"2006-01-02T15:04:05.000Z"'

 

常用方法

Object.freeze() 这个也好理解些,把东西冻结了就不能加、放、删东西了

Object.freeze() 静态方法可以使一个对象被冻结。冻结对象可以防止扩展,并使现有的属性不可写入和不可配置。被冻结的对象不能再被更改:不能添加新的属性,不能移除现有的属性,不能更改它们的可枚举性、可配置性、可写性或值,对象的原型也不能被重新指定。freeze() 返回与传入的对象相同的对象

const obj = {
  prop: 42,
};

Object.freeze(obj);

obj.prop = 33;
// Throws an error in strict mode

console.log(obj.prop);
// Expected output: 42

 

Object.isFrozen()

判断一个对象是否被冻结,和是一个函数配套使用,返回布尔类型值

 

const object1 = {
  property1: 42,
};

console.log(Object.isFrozen(object1));
// Expected output: false

Object.freeze(object1);

console.log(Object.isFrozen(object1));
// Expected output: true

 

 

Object.seal()

这个就和object.freez有些相似了,不同于他的是,通过 Object.seal() 密封的对象可以更改其现有属性,只要它们是可写的

 

密封一个对象会阻止其扩展并且使得现有属性不可配置。密封对象有一组固定的属性:不能添加新属性、不能删除现有属性或更改其可枚举性和可配置性、不能重新分配其原型。只要现有属性的值是可写的,它们仍然可以更改。seal() 返回传入的同一对象。

 
const object1 = {
  property1: 42,
};

Object.seal(object1);
object1.property1 = 33;
console.log(object1.property1);
// Expected output: 33

delete object1.property1; // Cannot delete when sealed
console.log(object1.property1);
// Expected output: 33

 

Object.is()

静态方法确定两个值是否为相同值

 

console.log(Object.is('1', 1));
// Expected output: false

console.log(Object.is(NaN, NaN));
// Expected output: true

console.log(Object.is(-0, 0));
// Expected output: false

const obj = {};
console.log(Object.is(obj, {}));
// Expected output: false

 

 

hasOwnPreperty()

返回一个布尔值,表示对象自有属性(而不是继承来的属性)中是否具有指定的属性。

 

const object1 = {};
object1.property1 = 42;

console.log(object1.hasOwnProperty('property1'));
// Expected output: true

console.log(object1.hasOwnProperty('toString'));
// Expected output: false

console.log(object1.hasOwnProperty('hasOwnProperty'));
// Expected output: false

 

 

 

propertyIsEnumerable()

返回一个布尔值,表示指定的属性是否是对象的可枚举自有属性。

const object1 = {};
const array1 = [];
object1.property1 = 42;
array1[0] = 42;

console.log(object1.propertyIsEnumerable('property1'));
// Expected output: true

console.log(array1.propertyIsEnumerable(0));
// Expected output: true

console.log(array1.propertyIsEnumerable('length'));
// Expected output: false

 

getOwnPropertyNames()

静态方法返回一个数组,其包含给定对象中所有自有属性(包括不可枚举属性,但不包括使用 symbol 值作为名称的属性)。

const object1 = {
  a: 1,
  b: 2,
  c: 3,
};

console.log(Object.getOwnPropertyNames(object1));
// Expected output: Array ["a", "b", "c"]

 

getOwnPropertyDescriptor()

静态方法返回一个对象,该对象描述给定对象上特定属性(即直接存在于对象上而不在对象的原型链中的属性)的配置。返回的对象是可变的,但对其进行更改不会影响原始属性的配置。

const object1 = {
  property1: 42,
};

const descriptor1 = Object.getOwnPropertyDescriptor(object1, 'property1');

console.log(descriptor1.configurable);
// Expected output: true

console.log(descriptor1.value);
// Expected output: 42

 

isPrototypeOf()

isPrototypeOf() 方法用于检查一个对象是否存在于另一个对象的原型链中。

function Foo() {}
function Bar() {}

Bar.prototype = Object.create(Foo.prototype);

const bar = new Bar();

console.log(Foo.prototype.isPrototypeOf(bar));
// Expected output: true
console.log(Bar.prototype.isPrototypeOf(bar));
// Expected output: true