Object 对象
构造函数
Object()
Object()
Object.prototype.constructor === Object
Object.__proto__ === Function.prototype
Object.prototype.constructor === Object
Object.__proto__ === Function.prototype
属性
name
length
__proto__
:指向对象的构造函数原型对象constructor
:指向该对象的构造函数
方法
方法 | 说明 | 返回值 |
---|---|---|
Object.is(obj1, obj2) | 比较两个值是否相等,取代 === 的缺陷 | boolean |
Object.create(obj) | 传入值为 null 为不继承 | |
assign() | 对象的合并 | |
freeze() | ||
isFronze() | ||
seal() | ||
isSealed() | ||
keys() | ||
values() | ||
entries() | 将一个键值对数组转为对象,不含继承属性 | |
defineProperty() | Vue2 数据劫持的实现方法 | |
defineProperties() | boolean | |
obj1.prototype.isPrototypeOf(obj2) | 判断 obj1 是否为 obj2 的原型 | |
Object.getPrototypeOf(obj) | 读取一个对象的原型对象 | 对象的原型 |
Object.setPrototypeOf(obj1, obj2) | 将 obj1 隐性原型指向 obj2 | |
Object.hasOwn(obj, prop) | ES6 是否为自身可遍历属性,静态方法 | |
obj.hasOwnProperty(prop) | 是否为自身可遍历属性,原型方法,有缺陷 | boolean |
obj.propertyIsEnumerable(prop) | 是否为自身可遍历可枚举属性 | boolean |
getOwnPropertyNames() | ||
Object.getOwnPropertyDescriptor() | ES5 | 对象某个属性的描述对象 |
Object.getOwnPropertyDescriptors() | ES2017 不含继承属性 | 对象所有属性的描述对象 |
getOwnPropertySymbols() | ||
toString() | ||
valueOf() | ||
apply() | ||
call() | ||
bind() | ||
constructor | 指向该对象的构造函数 | |
__proto__ | 读取或设置当前对象的原型对象 prototype | |
__defineGetter__ | ||
__defineSetter__ |
遍历
方法 | 参数 | 说明 | 返回值 |
---|---|---|---|
for...in | |||
keys | 新数组 | ||
values | 新数组 | ||
entries |
注意:Object
默认是不支持 for...of
遍历的,因为其没有部署 Symbol.Iterator
接口

判断属性是自身的还是继承的
foo.hasOwnProperty('bar') // ES5
Object.hasOwn(foo, 'a') // ES6
foo.hasOwnProperty('bar') // ES5
Object.hasOwn(foo, 'a') // ES6
检测方法 | 不可枚举属性 | 继承属性 |
---|---|---|
in | √ | √ |
has() | √ | √ |
hasOwnProperty() | × | × |
propertyIsEnumerable() | √ | × |
hasOwn() | × | × |
has
是in
的ES6
替代方案,是为了写法统一挂载到对象的静态方法hasOwn()
是hasOwnProperty()
的ES6+
替代方案,hasOwnProperty()
有一些缺点
setPrototypeOf() 与 getPrototypeOf()
Object.setPrototypeOf
方法的作用与 __proto__
相同,用来设置一个对象的原型对象(prototype
),返回参数对象本身。
因为 __proto__
规范只要去其在浏览器中要部署,所以标准增加了这个方法用于取代 __proto__
写法。
Object.create()
:生成操作Object.getPrototypeOf(obj)
:读操作Object.setPrototypeOf()
:写操作
function setPrototypeOf(obj1, obj2) {
obj1.__proto__ = obj2;
return obj1;
}
function setPrototypeOf(obj1, obj2) {
obj1.__proto__ = obj2;
return obj1;
}
对象属性简写
const o = {
method() {
return "Hello!";
}
};
// 等同于
const o = {
method: function() {
return "Hello!";
}
};
const o = {
method() {
return "Hello!";
}
};
// 等同于
const o = {
method: function() {
return "Hello!";
}
};
Object.assign 方法
主要用来合并对象:Object.assign(target, source1, source2);
。
注意点
- 同名属性,后面会覆盖前面
- 非
Object
类型会被转为Object
再合并 - 无法合并
undefined
与null
,因为它们无法被转为对象 - 实现的是浅拷贝
- 可以处理数组,但会当为对象处理,即下标一致会被覆盖
常用场景
- 为对象添加属性
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}
- 为对象添加方法
Object.assign(SomeClass.prototype, {
someMethod(arg1, arg2) {
// ···
},
anotherMethod() {
// ···
}
});
Object.assign(SomeClass.prototype, {
someMethod(arg1, arg2) {
// ···
},
anotherMethod() {
// ···
}
});
- 对象合并
- 浅拷贝
- 为对象属性设置默认值(组件中常用)
super 关键字
扩展运算符
...
链判断运算符
?.
题目
1. new
操作符具体干了什么呢?
- 创建一个空对象,并且
this
变量引用该对象,同时还继承了该函数的原型(prototype
)。 - 属性和方法被加入到
this
引用的对象中。 - 新创建的对象由
this
所引用,并且最后隐式的返回this
。
红宝书说法
- 创建一个新对象;
- 将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
- 执行构造函数中的代码(为这个新对象添加属性);
- 返回新对象
// 函数并未显式接受参数,而是通过内部 arguments 接收
function _new() {
var obj = new Object();
// 取出第一个参数,也就是传入的需要被实例化的函数
// [].shift.call(arguments) 等价于 Array.prototype.shift.call(arguments)
// 其返回值是第一个参数,也就是传入的方法,剩下的arguments已经不包含第一个参数了
Constructor = [].shift.call(arguments);
// 将对象的隐性原型指向传入函数的显式原型
obj.__proto__ = Constructor.prototype;
// 将参数传给传入的函数,并执行
var result = Constructor.apply(obj, arguments);
// 注意 null 与 function 情况
if((result && typeof result === 'object') || typeof result === 'function') {
return result;
} else {
return obj;
}
};
// 函数并未显式接受参数,而是通过内部 arguments 接收
function _new() {
var obj = new Object();
// 取出第一个参数,也就是传入的需要被实例化的函数
// [].shift.call(arguments) 等价于 Array.prototype.shift.call(arguments)
// 其返回值是第一个参数,也就是传入的方法,剩下的arguments已经不包含第一个参数了
Constructor = [].shift.call(arguments);
// 将对象的隐性原型指向传入函数的显式原型
obj.__proto__ = Constructor.prototype;
// 将参数传给传入的函数,并执行
var result = Constructor.apply(obj, arguments);
// 注意 null 与 function 情况
if((result && typeof result === 'object') || typeof result === 'function') {
return result;
} else {
return obj;
}
};
ES6
语法实现
function _new(fn, ...args){
const obj = Object.create(fn.prototype);
const result = fn.apply(obj, args);
// 如果函数返回 非空并是对象 返回 value 否则 返回 obj
return result instanceof Object ? result : obj;
}
function _new(fn, ...args){
const obj = Object.create(fn.prototype);
const result = fn.apply(obj, args);
// 如果函数返回 非空并是对象 返回 value 否则 返回 obj
return result instanceof Object ? result : obj;
}
使用:
function Person(name, age) {
this.name = name;
this.age = age;
}
let person = _new(Person, 'zhang', 18);
function Person(name, age) {
this.name = name;
this.age = age;
}
let person = _new(Person, 'zhang', 18);
2. 字面量 {} 、new Object() 与 Object.create() 的区别
- 字面量与
new Object()
创建的对象是一样的,都是Object
对象的实例,其__proto__ === Object.prototype
,继承了内置对象Object
Object.create()
方法创建的对象,一般与上面方式一样,只有当传入的参数为null
时,其将不会继承Object
的属性与方法
Object.create()
方法在 ES6
之前经常被用来实现继承。
function Shape() {
this.x = 0;
this.y = 0;
}
// superclass method
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
};
// Rectangle - subclass
function Rectangle() {
Shape.call(this); // call super constructor.
}
// subclass extends superclass
// 创建一个继承自 Shape 的对象
Rectangle.prototype = Object.create(Shape.prototype);
//If you don't set Rectangle.prototype.constructor to Rectangle,
//it will take the prototype.constructor of Shape (parent).
//To avoid that, we set the prototype.constructor to Rectangle (child).
Rectangle.prototype.constructor = Rectangle;
const rect = new Rectangle();
rect.move(1, 1); // Outputs, 'Shape moved.'
function Shape() {
this.x = 0;
this.y = 0;
}
// superclass method
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
};
// Rectangle - subclass
function Rectangle() {
Shape.call(this); // call super constructor.
}
// subclass extends superclass
// 创建一个继承自 Shape 的对象
Rectangle.prototype = Object.create(Shape.prototype);
//If you don't set Rectangle.prototype.constructor to Rectangle,
//it will take the prototype.constructor of Shape (parent).
//To avoid that, we set the prototype.constructor to Rectangle (child).
Rectangle.prototype.constructor = Rectangle;
const rect = new Rectangle();
rect.move(1, 1); // Outputs, 'Shape moved.'
3. ==
===
Object.is()
三种类型比较的区别
==
会先进行类型转换===
无法比较NaN
与+0、-0
Object.is(a, b)
为了解决===
存在的问题
4. prototype
、__proto__
与 constructor
三者的区别
__proto__
和constructor
属性是对象所独有的prototype
属性是函数所独有的- 因为在
JS
中函数也是一种对象,所以函数也拥有__proto__
和constructor
属性
5. __proto__
__proto__
属性是由一个对象指向一个对象,即指向它们的原型对象/父对象。
作用:当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的 __proto__
属性所指向的那个对象(可以理解为父对象)里找,如果父对象也不存在这个属性,则继续往父对象的 __proto__
属性所指向的那个对象里找,如果还没找到,则继续往上找…直到原型链顶端 null
,以上这种通过 __proto__
属性来连接对象直到 null
的链型查找方式就是原型链。
6. prototype
函数独有,它是从一个函数指向一个对象。它的含义是函数的原型对象。返回对象类型原型的引用。
作用:让该函数实例化的对象都可以继承函数的所有属性与方法。
任何函数在创建的时候,会默认同时创建该函数的 prototype
对象。
function
定义的对象有一个 prototype
属性,prototype
属性又指向了一个 prototype
对象,注意 prototype
属性与 prototype
对象是两个不同的东西,注意区别。在 prototype
对象中又有一个 constructor
属性,这个 constructor
属性同样指向一个 constructor
对象,而这个 constructor
对象恰恰就是这个 function
函数本身。
function Fn() {}
new Fn().__proto__ === Fn.prototype
Fn.prototype.constructor === Fn
Fn.prototype.__proto__ === Object.prototype
function Fn() {}
new Fn().__proto__ === Fn.prototype
Fn.prototype.constructor === Fn
Fn.prototype.__proto__ === Object.prototype
7. constructor
constructor
属性也是对象才拥有的,它是从一个对象指向一个函数,返回创建此对象的函数的引用。
作用:指向该对象的构造函数,每个对象都有构造函数。
constructor
属性是专门为 function
而设计的,它存在于每一个 function
的 prototype
属性中,这个 constructor
保存了指向 function
的一个引用。
综合
function A(){
}
let b = "字符串";
let c = new A();
// 输出该属性
console.log(b.__proto__); // String {'', constructor: ƒ, anchor: ƒ, big: ƒ, blink: ƒ, …}
console.log(c.__proto__); // {constructor: ƒ}
console.log(c.__proto__ === A.prototype); // true
// 将prototype展开的构造函数就是A本身也是c的构造函数
A.prototype.constructor === A === c.constructor
c.__proto __ === c.constructor.prototype === A.prototype
function A(){
}
let b = "字符串";
let c = new A();
// 输出该属性
console.log(b.__proto__); // String {'', constructor: ƒ, anchor: ƒ, big: ƒ, blink: ƒ, …}
console.log(c.__proto__); // {constructor: ƒ}
console.log(c.__proto__ === A.prototype); // true
// 将prototype展开的构造函数就是A本身也是c的构造函数
A.prototype.constructor === A === c.constructor
c.__proto __ === c.constructor.prototype === A.prototype
Function instanceof Object
与 Object instanceof Function
原因
Function.__proto__.__proto__ === Object.prototype
Object.__proto__ === Function.prototype
Function.__proto__.__proto__ === Object.prototype
Object.__proto__ === Function.prototype