Object 对象
构造函数
Object()Object()Object.prototype.constructor === Object
Object.__proto__ === Function.prototypeObject.prototype.constructor === Object
Object.__proto__ === Function.prototype属性
namelength__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') // ES6foo.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、-0Object.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.prototypefunction Fn() {}
new Fn().__proto__ === Fn.prototype
Fn.prototype.constructor === Fn
Fn.prototype.__proto__ === Object.prototype7. 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.prototypefunction 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.prototypeFunction instanceof Object 与 Object instanceof Function 原因
Function.__proto__.__proto__ === Object.prototype
Object.__proto__ === Function.prototypeFunction.__proto__.__proto__ === Object.prototype
Object.__proto__ === Function.prototype
前端知识点