all
Object()
Object是JavaScript的一种 数据类型 。它用于存储各种键值集合和更复杂的实体。Objects可以通过 **Object()**构造函数或者使用 对象字面量 的方式创建。Object构造函数为给定的参数创建一个包装类对象(object wrapper),具体有以下情况:
- 如果给定值是 null 或 undefined,将会创建并返回一个空对象
- 如果传进去的是一个基本类型的值,则会构造其包装类型的对象
- 如果传进去的是引用类型的值,仍然会返回这个值,经他们复制的变量保有和源对象相同的引用地址
语法:
let num = 123;
let numObj1 = new Number(num); // 通过 new Number() 转换成类型对象
console.log(numObj1); // 结果为 Number {123}
let numOjb2 = Object(num); // 通过 Object() 转换成类型对象
console.log(numOjb2); // 结果为 Number {123}
let str = 'abc';
let strObj1 = new String(str); // 通过 new String() 转换成类型对象
console.log(strObj1); // 结果 String {'abc'}
let strObj2 = Object(str); // 通过 Object() 转换成类型对象
console.log(strObj2); // 结果 String {'abc'}
let bool = true;
let boolObj1 = new Boolean(bool); // 通过 new Boolean() 转换成类型对象
console.log(boolObj1); // 结果 Boolean {true}
let boolObj2 = Object(bool); // 通过 Object() 转换成类型对象
console.log(boolObj2); // 结果 Boolean {true}
Object.assign()
Object.assign() 方法用于从一个或多个源对象拷贝自身可枚举的属性(String属性和Symbol属性),并且覆盖目标对象的同名属性。将所有可枚举属性的值分配到目标对象。它将返回目标对象。 **Object.assign()**中的目标对象不可以是null
或者undefined
,否则会报错。**Object.assign()**中的源对象对象如果是null
或者undefined
,会直接跳过。
语法
Object.assign(target, ...sources)
- target: 目标对象。
- sources: 源对象。
返回值
目标对象。
应用场景
-
拷贝对象: 拷贝源对象自身可枚举的属性(String属性和Symbol属性),并且覆盖目标对象的同名属性。
const s1Symbol = Symbol('s1');
const s2Symbol = Symbol('s2');
const obj1 = {
type1:'obj1',
[s1Symbol]:'s1Symbol'
}
Object.defineProperty(obj1,'value1',{
value:'哈哈',
writable:true,
enumerable:false,
configurable:true
});
const obj2 = {
type2:'obj2',
[s2Symbol]:'s2Symbol'
}
Object.defineProperty(obj2,'value2',{
value:'哈哈',
writable:true,
enumerable:true,
configurable:true
});
const obj = Object.assign({},obj1,obj2);
console.log(obj); // {type1: 'obj1', type2: 'obj2', value2: '哈哈', Symbol(s1): 's1Symbol', Symbol(s2): 's2Symbol'} -
Object.assign()
中的目标对象为null
或者undefined
会报错: Object.assign() 中的目标对象不可以是 null 或者undefinedconst s1Symbol = Symbol('s1');
const s2Symbol = Symbol('s2');
const obj1 = {
type1:'obj1',
[s1Symbol]:'s1Symbol'
}
Object.defineProperty(obj1,'value1',{
value:'哈哈',
writable:true,
enumerable:false,
configurable:true
});
const obj2 = {
type2:'obj2',
[s2Symbol]:'s2Symbol'
}
Object.defineProperty(obj2,'value2',{
value:'哈哈',
writable:true,
enumerable:true,
configurable:true
});
const obj = Object.assign(null,obj1,obj2);
console.log(obj); // Cannot convert undefined or null to object
原理(Polyfill)
这个polyfill不支持symbol属性, 由于 ES5 中本来就不存在 symbols :
Object.assign = function(target){
if(target === null || target === undefined){
throw new TypeError('Cannot convert undefined or null to object');
}
var object = Object(target);
for(var index=1; index < arguments.length ; index++){
var nextSource = arguments[index];
if(nextSource !== null && nextSource !== undefined){
for(var nextKey in nextSource){
if(Object.prototype.hasOwnProperty.call(nextSource,nextKey)){
object[nextKey] = nextSource[nextKey];
}
}
}
}
return object;
}
const obj1 = {
type1:'obj1',
}
Object.defineProperty(obj1,'value1',{
value:'哈哈',
writable:true,
enumerable:false,
configurable:true
});
const obj2 = {
type2:'obj2',
}
Object.defineProperty(obj2,'value2',{
value:'哈哈',
writable:true,
enumerable:true,
configurable:true
});
const obj = Object.assign({},obj1,obj2);
console.log(obj); // {type1: 'obj1', type2: 'obj2', value2: '哈哈'}
Object.create()
Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的proto。
语法
Object.create(proto,[propertiesObject])
- proto: 新创建对象的原型对象。
- propertiesObject: 可选。需要传入一个对象,该对象的属性类型参照Object.defineProperties()的第二个参数。如果该参数被指定且不为 undefined,该传入对象的自有可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符。
Object.create()
的第二个参数与Object.defineProperties()
的第二个参数一样:每个新增属性都通过各自的描述符来描述。以这种方式添加的属性会遮蔽原型对象上的同名属性。
返回值
一个新对象,带着指定的原型对象和属性。
应用场景
-
通过
Object.create()
创建对象const prototype = {
type:'prototype'
}
const obj = Object.create(prototype,{
name:{
value:'obj',
writable:true,
enumerable:true,
configurable:true
},
type:{
value:'obj对象',
writable:true,
enumerable:true,
configurable:true
}
});
console.log(obj); // {name: 'obj', type: 'obj对象' [[Prototype]]: {type: "prototype"}} -
实现原型式继承
const person = {
name: "一个人",
friends: ["小明", "小红"],
};
const anotherPerson1 = Object.create(person, {
name: {
value: "另一个人",
writable: true,
enurmable: true,
configurable: true,
},
friends: {
value: ["另一个人的小明", "另一个人的小红"],
writable: true,
enurmable: true,
configurable: true,
},
});
console.log(anotherPerson1);
// F {}
// [[Prototype]]: Object
// friends: (2)['小明', '小红']
// name: "一个人"
// [[Prototype]]: Object
const anotherPerson2 = Object.create(person, {
name: {
value: "另一个人",
writable: true,
enurmable: true,
configurable: true,
},
friends: {
value: ["另一个人的小明", "另一个人的小红"],
writable: true,
enurmable: true,
configurable: true,
},
});
console.log(anotherPerson2);
原理(Polyfill)
Object.create = function (obj, descriptorMap) {
function converToDescriptor(descriptor) {
function hasProperty(obj, property) {
return Object.prototype.hasOwnProperty.call(obj, property);
}
var descriptorNew = {};
if (hasProperty(descriptor, "value")) {
descriptorNew.value = descriptor.value;
}
if (hasProperty(descriptor, "writable")) {
descriptorNew.writable = !!descriptor.writable;
}
if (hasProperty(descriptor, "enurmable")) {
descriptorNew.enumerable = !!descriptor.enumerable;
}
if (hasProperty(descriptor, "configurable")) {
descriptorNew.configurable = !!descriptor.configurable;
}
if (hasProperty(descriptor, "get")) {
var g = descriptor.get;
if (typeof g !== "function" && g != null) {
throw new TypeError("bad get");
}
descriptorNew.get = g;
}
if (hasProperty(descriptor, "set")) {
var s = descriptor.set;
if (typeof s !== "function" && s != null) {
throw new TypeError("bad set");
}
descriptorNew.set = s;
}
if (
("get" in descriptorNew || "set" in descriptorNew) &&
("value" in descriptorNew || "writable" in descriptorNew)
) {
throw new TypeError("identify-confused descriptor");
}
return descriptorNew;
}
if (typeof obj !== "object" && typeof obj !== "function") {
throw new TypeError(
"Object.create support only object as the first argument"
);
} else if (obj == null) {
throw new TypeError(
"Object.create support only object as the first argument"
);
}
if (typeof descriptorMap !== "object" && descriptorMap != null) {
throw new TypeError(
"Object.create support only object as the second argument"
);
}
function F() {}
F.prototype = obj;
var objNew = new F();
var keyArray = Object.keys(descriptorMap);
var descriptorArray = [];
for (var i = 0; i < keyArray.length; i++) {
descriptorArray.push([
keyArray[i],
converToDescriptor(descriptorMap[keyArray[i]]),
]);
}
for (var i = 0; i < descriptorArray.length; i++) {
Object.defineProperty(
objNew,
descriptorArray[i][0],
descriptorArray[i][1]
);
}
return objNew;
};
const obj = Object.create({},{
name:{
value:'柏拉图',
writable:true,
enurmable:true,
configurable:true
},
age:{
value:23,
writable:true,
enumerable:true,
configurable:true
}
});
console.log(obj);
Object.defineProperties()
**Object.defineProperties()**方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
语法
Object.defineProperties(obj, props)
- obj: 在其上定义或修改属性的对象。
- props: 要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符(更多详情,请参阅Object.defineProperty())。
返回值
应用场景
-
创建、修改、删除属性
-
通过数据描述符创建、修改、删除属性
const obj = {};
Object.defineProperties(obj,{
name:{
value:'柏拉图',
writable:true,
enumerable:true,
configurable:true
},
age:{
value:23,
writable:true,
enumerable:true,
configurable:true
}
});
console.log(obj.name);
console.log(obj.age);
obj.name = '柏拉图修改';
obj.age = '23修改';
console.log(obj.name);
console.log(obj.age);
for(let key in obj){
console.log(key);
}
delete obj.name;
delete obj.age;
console.log(obj); -
通过存取描述符创建、修改、删除属性
const obj = {};
Object.defineProperties(obj,{
name:{
enumerable:true,
configurable:true,
get(){
console.log('访问操作');
return this._name;
},
set(newValue){
console.log('设置操作');
this._name = newValue;
}
},
age:{
enumerable:true,
configurable:true,
get(){
console.log('访问操作');
return this._age;
},
set(newValue){
console.log('设置操作');
this._age = newValue;
}
}
});
console.log(obj.name);
console.log(obj.age);
obj.name = '柏拉图修改';
obj.age = '23修改';
console.log(obj.name);
console.log(obj.age);
for(let key in obj){
console.log(key);
}
delete obj.name;
delete obj.age;
console.log(obj);
-
原理(Polyfill)
Object.defineProperties = function (obj, properties) {
function converToDescriptor(desc) {
function hasProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
if (typeof desc !== "object" || desc === null) {
throw new TypeError("bad desc");
}
var descriptor = {};
if (hasProperty(desc, "enumerable")) {
descriptor.enumerable = !!desc.enumerable;
}
if (hasProperty(desc, "configurable")) {
descriptor.configurable = !!desc.configurable;
}
if(hasProperty(desc,'value')){
descriptor.value = desc.value;
}
if(hasProperty(desc,'writable')){
descriptor.writable = !!desc.writable;
}
if(hasProperty(desc,'get')){
var g = desc.get;
if(!typeof g === "function" && typeof g !== 'undefined'){
throw new TypeError('bad get');
}
descriptor.get = g;
}
if(hasProperty(desc,'set')){
var s = desc.set;
if(!typeof s === "function" && typeof s !== "undefined"){
throw new TypeError("bad set");
}
descriptor.set = s;
}
if(('get' in descriptor || 'set' in descriptor) && ('value' in descriptor || 'writable' in descriptor)){
throw new TypeError('identity-confused descriptor');
}
return descriptor;
}
if(typeof obj !== 'object' || obj === null){
throw new TypeError('bad obj');
}
var propertiesObj = Object(properties);
var keyArray = Object.keys(propertiesObj);
var descriptorArray = [];
for(var i=0;i<keyArray.length;i++){
console.log(converToDesCriptor(propertiesObj[keyArray[i]]));
descriptorArray.push([keyArray[i],converToDesCriptor(propertiesObj[keyArray[i]])]);
}
for(var i=0;i<descriptorArray.length;i++){
Object.defineProperty(obj,descriptorArray[i][0],descriptorArray[i][1]);
}
console.log(obj);
return obj;
};
const obj = {};
Object.defineProperties(obj, {
name: {
value: "柏拉图",
writable: true,
enumerable: true,
configurable: true,
},
age: {
value: 23,
writable: true,
enumerable: true,
configurable: true,
},
});
console.log(obj);
Object.entries()
Object.entries()
方法返回一个给定对象自身****可枚举属性的键值对数组,
语法
Object.entries(obj)
- obj: 可以返回其可枚举属性的键值对的对象。
返回值
给定对象自身可枚举属性的键值对数组。
应用场景
经典问题
-
如何遍历对象属性?有几种方法以及各自的特点?
-
通过
Object.keys(obj)
遍历对象属性,获取的是对象自身的所有可枚举属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
console.log(Object.keys(obj)); // ['name'] -
通过
for……in
遍历对象属性,获取的是对象自身以及对象原型上的所有可枚举属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
for(let key in obj){
console.log(key); // 输出 name nameProto ageProto
} -
通过
Object.getOwnPropertyNames(obj)
遍历,获取的是对象自身所有可枚举和不可枚举属性。const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const result = Object.getOwnPropertyNames(obj);
console.log(result); ['name', 'age'] -
通过
Object.entries(obj)
遍历属性,获取的是对象自身可枚举属性键值对数组const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const result = Object.entries(obj);
console.log(result); /// [0: (2) ['name', '柏拉图']]
-
-
如何获取对象
自身
所有可枚举属性?有几种方法?-
通过
Object.keys(obj)
遍历对象属性,获取的是对象自身的所有可枚举属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
console.log(Object.keys(obj)); // ['name'] -
通过
for……in
遍历对象属性,获取的是对象自身以及对象原型上的所有可枚举属性,然后通过obj.hasOwnProperty(prop)
进行过滤const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
for(let key in obj){
if(obj.hasOwnProperty(key)){
console.log(key); // 输出 name
}
}
-
-
如何获取对象
自身
所有不可枚举属性?有几种方法?-
通过
Object.getOwnPropertyNames(obj)
遍历,获取的是对象自身所有可枚举和不可枚举属性。然后通过Object.keys(obj)
过滤const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const allSelfEnumerable = Object.keys(obj);
const result = Object.getOwnPropertyNames(obj).filter(key=>{
if(!allSelfEnumerable.includes(key)){
return true;
}
return false;
});
console.log(result); // ['age']
-
-
如何获取对象
自身
所有可枚举和不可枚举属性?有几种方法?-
通过
Object.getOwnPropertyNames(obj)
遍历,获取的是对象自身所有可枚举和不可枚举属性。const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const result = Object.getOwnPropertyNames(obj);
console.log(result); ['name', 'age']
-
原理(Polyfill)
Object.entries = function(obj){
var keyArray = Object.keys(obj);
var length = keyArray.length;
var result = new Array(length);
var index = 0;
while(index < length){
result[index] = [keyArray[index],obj[keyArray[index]]];
index++;
}
return result;
}
const obj = {
type:'对象',
data:[]
}
console.log(Object.entries(obj));
Object.freeze()
Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。
语法
Object.freeze(obj)
- obj: 要被冻结的对象。
返回值
被冻结的对象。
应用场景
-
冻结对象
const obj = {
name: "柏拉图",
age: 23,
};
Object.freeze(obj);
obj.like = '编程'; // 已冻结对象不可添加新属性,添加失效
obj.name = '柏拉图修改'; // 已冻结对象不可修改属性,修改失效
delete obj.name; // 已冻结对象不可删除属性,删除失效
console.log(obj); -
冻结数组
const array = ['哈哈','呵呵'];
Object.freeze(array);
array[0] = '哈哈修改';
console.log(array[0]); // 哈哈
经典问题
-
如何使对象变得不可扩展?有几种方法可以实现
-
通过
Object.seal(obj)
变得不可扩展const obj = {
name: "柏拉图",
age: 23,
};
if (Object.isExtensible(obj)) {
Object.seal(obj);
}
obj.like = "编程";
console.log(obj); // {name: '柏拉图', age: 23} -
通过
Object.freeze()
变得不可扩展const obj = {
name: "柏拉图",
age: 23,
};
if (Object.isExtensible(obj)) {
Object.freeze(obj);
}
obj.like = "编程";
console.log(obj); // {name: '柏拉图', age: 23} -
通过
Object.preventExtensions(obj)
变得不可扩展const obj = {
name: "柏拉图",
age: 23,
};
if (Object.isExtensible(obj)) {
Object.preventExtensions(obj);
}
obj.like = "编程";
console.log(obj); // {name: '柏拉图', age: 23}
-
原理(Polyfill)
Object.fromEntries()
**Object.fromEntries()**方法把键值对列表转换为一个对象。
语法
Object.fromEntries(iterable);
- iterable: 类似 Array 、 Map 或者其它实现了可迭代协议的可迭代对象。
返回值
一个由该迭代对象条目提供对应属性的新对象。
应用场景
-
Map
转化为Object
const map = new Map([['name','柏拉图'],['age',23]]);
console.log(map); // Map(2) {'name' => '柏拉图', 'age' => 23}
const mapObj = Object.fromEntries(map);
console.log(mapObj); // {name: '柏拉图', age: 23} -
Array
转化为Object
const array = [
["name", "柏拉图"],
["age", 23],
];
console.log(array); // (2) [Array(2), Array(2)]
const arrayObj = Object.fromEntries(array);
console.log(arrayObj); // {name: '柏拉图', age: 23} -
查询字符串转化为
Object
const urlString = 'id=44444×tamp=43432432432'
const urlParams = new URLSearchParams(urlString);
const urlParamsObj = Object.fromEntries(urlParams);
console.log(urlParamsObj); // {id: '44444', timestamp: '43432432432'}
原理(Polyfill)
Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
语法
Object.getOwnPropertyDescriptor(obj, prop)
- obj: 需要查找的目标对象
- prop: 目标对象内属性名称
返回值
如果指定的属性存在于对象上,则返回其属性描述符对象(property descriptor),否则返回 undefined。
应用场景
-
获取对象属性描述符
const obj = {};
Object.defineProperties(obj,{
name:{
enumerable:true,
configurable:true,
get(){
console.log('访问操作');
return this._name;
},
set(newValue){
console.log('设置操作');
this._name = newValue;
}
},
age:{
enumerable:true,
configurable:true,
get(){
console.log('访问操作');
return this._age;
},
set(newValue){
console.log('设置操作');
this._age = newValue;
}
}
});
const nameDescriptor = Object.getOwnPropertyDescriptor(obj,'name');
const ageDescriptor = Object.getOwnPropertyDescriptor(obj,'age');
console.log(nameDescriptor); // {enumerable: true, configurable: true, get: ƒ, set: ƒ}
console.log(ageDescriptor); // {enumerable: true, configurable: true, get: ƒ, set: ƒ}
原理(Polyfill)
Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors() 方法用来获取一个对象的所有自身属性的描述符。
语法
Object.getOwnPropertyDescriptors(obj)
- obj: 任意对象
返回值
所指定对象的所有自身属性的描述符,如果没有任何自身属性,则返回空对象。
应用场景
-
获取对象自身所有描述符
const obj = {};
Object.defineProperties(obj,{
name:{
enumerable:true,
configurable:true,
get(){
console.log('访问操作');
return this._name;
},
set(newValue){
console.log('设置操作');
this._name = newValue;
}
},
age:{
enumerable:true,
configurable:true,
get(){
console.log('访问操作');
return this._age;
},
set(newValue){
console.log('设置操作');
this._age = newValue;
}
}
});
const descriptors = Object.getOwnPropertyDescriptors(obj);
console.log(descriptors);
// 结果为:
// {name: {…}, age: {…}}
// age: {enumerable: true, configurable: true, get: ƒ, set: ƒ}
// name: {enumerable: true, configurable: true, get: ƒ, set: ƒ}
// [[Prototype]]: Objects
原理(Polyfill)
Object.getOwnPropertyNames()
Object.getOwnPropertyNames()
方法返回对象自身****可枚举和不可枚举属性(但不包括Symbol值作为名称的属性)。
语法
Object.getOwnPropertyNames(obj)
- obj: 一个对象,其自身的可枚举和不可枚举属性的名称被返回。
返回值
在给定对象上找到的自身属性对应的字符串数组。
应用场景
-
获取对象
自身
中可枚举
和不可枚举
的属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const result = Object.getOwnPropertyNames(obj);
console.log(result); // ['name', 'age'] -
获取对象
自身
中可枚举
属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const allEnumerable = Object.keys(obj);
const result = Object.getOwnPropertyNames(obj).filter(key=>{
if(allEnumerable.includes(key)){
return true
}
return false;
});
console.log(result); // ['name'] -
获取对象
自身
中不可枚举
的属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const allEnumerable = Object.keys(obj);
const result = Object.getOwnPropertyNames(obj).filter(key=>{
if(!allEnumerable.includes(key)){
return true
}
return false;
});
console.log(result); // ['age']
经典问题
-
如何遍历对象属性?有几种方法以及各自的特点?
-
通过
Object.keys(obj)
遍历对象属性,获取的是对象自身的所有可枚举属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
console.log(Object.keys(obj)); // ['name'] -
通过
for……in
遍历对象属性,获取的是对象自身以及对象原型上的所有可枚举属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
for(let key in obj){
console.log(key); // 输出 name nameProto ageProto
} -
通过
Object.getOwnPropertyNames(obj)
遍历,获取的是对象自身所有可枚举和不可枚举属性。const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const result = Object.getOwnPropertyNames(obj);
console.log(result); ['name', 'age'] -
通过
Object.entries(obj)
遍历属性,获取的是对象自身可枚举属性键值对数组const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const result = Object.entries(obj);
console.log(result); /// [0: (2) ['name', '柏拉图']]
-
-
如何获取对象
自身
所有可枚举属性?有几种方法?-
通过
Object.keys(obj)
遍历对象属性,获取的是对象自身的所有可枚举属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
console.log(Object.keys(obj)); // ['name'] -
通过
for……in
遍历对象属性,获取的是对象自身以及对象原型上的所有可枚举属性,然后通过obj.hasOwnProperty(prop)
进行过滤const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
for(let key in obj){
if(obj.hasOwnProperty(key)){
console.log(key); // 输出 name
}
}
-
-
如何获取对象
自身
所有不可枚举属性?有几种方法?-
通过
Object.getOwnPropertyNames(obj)
遍历,获取的是对象自身所有可枚举和不可枚举属性。然后通过Object.keys(obj)
过滤const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const allSelfEnumerable = Object.keys(obj);
const result = Object.getOwnPropertyNames(obj).filter(key=>{
if(!allSelfEnumerable.includes(key)){
return true;
}
return false;
});
console.log(result); // ['age']
-
-
如何获取对象
自身
所有可枚举和不可枚举属性?有几种方法?-
通过
Object.getOwnPropertyNames(obj)
遍历,获取的是对象自身所有可枚举和不可枚举属性。const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const result = Object.getOwnPropertyNames(obj);
console.log(result); ['name', 'age']
-
原理(Polyfill)
Object.getOwnPropertySymbols()
语法
返回值
应用场景
原理(Polyfill)
Object.getPrototypeOf()
Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)。
语法
Object.getPrototypeOf(object)
- obj: 要返回其原型的对象。
返回值
给定对象的原型。如果没有继承属性,则返回 null 。
应用场景
-
获取对象原型
var proto = {};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true
原理(Polyfill)
Object.prototype.hasOwnProperty()
hasOwnProperty()
方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(包括可枚举属性和不可枚举属性)。
语法
obj.hasOwnProperty(prop)
- prop: 要检测的属性的 String 字符串形式表示的名称,或者 Symbol。
返回值
用来判断某个对象是否含有指定的属性的布尔值 Boolean。
应用场景
-
检测对象自身是否具有属性
const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
console.log(obj.hasOwnProperty('name'));
console.log(obj.hasOwnProperty('age')); -
遍历对象自身所有可枚举属性
const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
for(let key in obj){
if(obj.hasOwnProperty(key)){
console.log(key); // 输出 name
}
}
经典问题
-
如何遍历对象属性?有几种方法以及各自的特点?
-
通过
Object.keys(obj)
遍历对象属性,获取的是对象自身的所有可枚举属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
console.log(Object.keys(obj)); // ['name'] -
通过
for……in
遍历对象属性,获取的是对象自身以及对象原型上的所有可枚举属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
for(let key in obj){
console.log(key); // 输出 name nameProto ageProto
} -
通过
Object.getOwnPropertyNames(obj)
遍历,获取的是对象自身所有可枚举和不可枚举属性。const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const result = Object.getOwnPropertyNames(obj);
console.log(result); ['name', 'age'] -
通过
Object.entries(obj)
遍历属性,获取的是对象自身可枚举属性键值对数组const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const result = Object.entries(obj);
console.log(result); /// [0: (2) ['name', '柏拉图']]
-
-
如何获取对象
自身
所有可枚举属性?有几种方法?-
通过
Object.keys(obj)
遍历对象属性,获取的是对象自身的所有可枚举属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
console.log(Object.keys(obj)); // ['name'] -
通过
for……in
遍历对象属性,获取的是对象自身以及对象原型上的所有可枚举属性,然后通过obj.hasOwnProperty(prop)
进行过滤const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
for(let key in obj){
if(obj.hasOwnProperty(key)){
console.log(key); // 输出 name
}
}
-
-
如何获取对象
自身
所有不可枚举属性?有几种方法?-
通过
Object.getOwnPropertyNames(obj)
遍历,获取的是对象自身所有可枚举和不可枚举属性。然后通过Object.keys(obj)
过滤const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const allSelfEnumerable = Object.keys(obj);
const result = Object.getOwnPropertyNames(obj).filter(key=>{
if(!allSelfEnumerable.includes(key)){
return true;
}
return false;
});
console.log(result); // ['age']
-
-
如何获取对象
自身
所有可枚举和不可枚举属性?有几种方法?-
通过
Object.getOwnPropertyNames(obj)
遍历,获取的是对象自身所有可枚举和不可枚举属性。const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const result = Object.getOwnPropertyNames(obj);
console.log(result); ['name', 'age']
-
原理(Polyfill)
Object.isExtensible()
Object.isExtensible() 方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。
语法
Object.isExtensible(obj)
- obj: 需要检测的对象
返回值
表示给定对象是否可扩展的一个Boolean 。
应用场景
-
检测对象是否可扩展,如果之前可扩展,之后变得不可扩展
-
通过
Object.seal(obj)
变得不可扩展const obj = {
name: "柏拉图",
age: 23,
};
if (Object.isExtensible(obj)) {
Object.seal(obj);
}
obj.like = "编程";
console.log(obj); // {name: '柏拉图', age: 23} -
通过
Object.freeze()
变得不可扩展const obj = {
name: "柏拉图",
age: 23,
};
if (Object.isExtensible(obj)) {
Object.freeze(obj);
}
obj.like = "编程";
console.log(obj); // {name: '柏拉图', age: 23} -
通过
Object.preventExtensions(obj)
变得不可扩展const obj = {
name: "柏拉图",
age: 23,
};
if (Object.isExtensible(obj)) {
Object.preventExtensions(obj);
}
obj.like = "编程";
console.log(obj); // {name: '柏拉图', age: 23}
-
原理(Polyfill)
Object.isFrozen()
**Object.isFrozen()**方法判断一个对象是否被冻结。
语法
Object.isFrozen(obj)
- obj: 被检测的对象。
返回值
表示给定对象是否被冻结的Boolean。
应用场景
-
检测对象是否冻结,如果未冻结,将对象冻结
const obj = {
name: "柏拉图",
age: 23,
};
if (!Object.isFrozen(obj)) {
Object.freeze(obj);
}
obj.like = "编程"; // 已冻结对象不可添加新属性,添加失效
obj.name = "柏拉图修改"; // 已冻结对象不可修改属性,修改失效
delete obj.name; // 已冻结对象不可删除属性,删除失效
console.log(obj);
原理(Polyfill)
Object.prototype.isPrototypeOf()
isPrototypeOf()
方法用于测试一个对象是否存在于另一个对象的原型链上。
isPrototypeOf()
与instanceof
有什么区别?
-
a.isPrototypeOf(b)
: 针对a
本身进行检查 -
b instanceof b
: 针对b.prototype
进行检查
语法
prototypeObj.isPrototypeOf(object)
object
: 在该对象的原型链上搜寻
返回值
Boolean
,表示调用对象是否在另一个对象的原型链上。
应用场景
原理(Polyfill)
Object.isSealed()
Object.isSealed() 方法判断一个对象是否被密封。
语法
Object.isSealed(obj)
- obj: 要被检查的对象。
返回值
表示给定对象是否被密封的一个Boolean 。
应用场景
-
检测对象是否密封,如果未密封,将对象密封
const obj = {
name: "柏拉图",
age: 23,
};
if (Object.isSealed(obj)) {
Object.seal(obj);
}
obj.like = "编程"; // 已密封对象不可添加新属性,添加失效
obj.name = "柏拉图修改"; // 已密封对象可修改属性,修改成功
delete obj.name; // 已密封对象不可删除属性,删除失效
console.log(obj);
Object.defineProperty(obj, "name", {
// 尝试为密封对象的属性重新配置描述符,失败
value: "柏拉图精确管理属性",
writable: true,
enumerable: true,
configurable: true,
});
console.log(obj);
原理(Polyfill)
Object.keys()
Object.keys() 方法会返回一个由一个给定对象的自身****可枚举属性组成的数组。
语法
Object.keys(obj)
- obj: 要返回其枚举自身属性的对象。
返回值
一个表示给定对象自身
的所有可枚举
属性的字符串数组。
应用场景
-
获取对象
自身
所有可枚举属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
console.log(Object.keys(obj)); // ['name']
经典问题
-
如何遍历对象属性?有几种方法以及各自的特点?
-
通过
Object.keys(obj)
遍历对象属性,获取的是对象自身的所有可枚举属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
console.log(Object.keys(obj)); // ['name'] -
通过
for……in
遍历对象属性,获取的是对象自身以及对象原型上的所有可枚举属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
for(let key in obj){
console.log(key); // 输出 name nameProto ageProto
} -
通过
Object.getOwnPropertyNames(obj)
遍历,获取的是对象自身所有可枚举和不可枚举属性。const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const result = Object.getOwnPropertyNames(obj);
console.log(result); ['name', 'age'] -
通过
Object.entries(obj)
遍历属性,获取的是对象自身可枚举属性键值对数组const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const result = Object.entries(obj);
console.log(result); /// [0: (2) ['name', '柏拉图']]
-
-
如何获取对象
自身
所有可枚举属性?有几种方法?-
通过
Object.keys(obj)
遍历对象属性,获取的是对象自身的所有可枚举属性const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
console.log(Object.keys(obj)); // ['name'] -
通过
for……in
遍历对象属性,获取的是对象自身以及对象原型上的所有可枚举属性,然后通过obj.hasOwnProperty(prop)
进行过滤const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
for(let key in obj){
if(obj.hasOwnProperty(key)){
console.log(key); // 输出 name
}
}
-
-
如何获取对象
自身
所有不可枚举属性?有几种方法?-
通过
Object.getOwnPropertyNames(obj)
遍历,获取的是对象自身所有可枚举和不可枚举属性。然后通过Object.keys(obj)
过滤const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const allSelfEnumerable = Object.keys(obj);
const result = Object.getOwnPropertyNames(obj).filter(key=>{
if(!allSelfEnumerable.includes(key)){
return true;
}
return false;
});
console.log(result); // ['age']
-
-
如何获取对象
自身
所有可枚举和不可枚举属性?有几种方法?-
通过
Object.getOwnPropertyNames(obj)
遍历,获取的是对象自身所有可枚举和不可枚举属性。const obj = {};
Object.defineProperty(obj,'name',{
value:'柏拉图',
writable:true,
enumerable:true, // 属性可枚举
configurable:true
});
Object.defineProperty(obj,'age',{
value:'柏拉图',
writable:true,
enumerable:false, // 属性不可枚举
configurable:true
});
obj.__proto__ = {
nameProto:'柏拉图',
ageProto:23
}
const result = Object.getOwnPropertyNames(obj);
console.log(result); ['name', 'age']
-
原理(Polyfill)
Object.preventExtensions()
**Object.preventExtensions()**方法让一个对象变的不可扩展,也就是永远不能再添加新的属性。
语法
Object.preventExtensions(obj)
- obj: 将要变得不可扩展的对象。
返回值
已经不可扩展的对象。
应用场景
-
将对象变为不可扩展的对象
const obj = {
name:'柏拉图',
age:23
}
Object.preventExtensions(obj);
obj.like = '编程';
console.log(obj); // {name: '柏拉图', age: 23}
经典问题
-
如何使对象变得不可扩展?有几种方法可以实现
-
通过
Object.seal(obj)
变得不可扩展const obj = {
name: "柏拉图",
age: 23,
};
if (Object.isExtensible(obj)) {
Object.seal(obj);
}
obj.like = "编程";
console.log(obj); // {name: '柏拉图', age: 23} -
通过
Object.freeze()
变得不可扩展const obj = {
name: "柏拉图",
age: 23,
};
if (Object.isExtensible(obj)) {
Object.freeze(obj);
}
obj.like = "编程";
console.log(obj); // {name: '柏拉图', age: 23} -
通过
Object.preventExtensions(obj)
变得不可扩展const obj = {
name: "柏拉图",
age: 23,
};
if (Object.isExtensible(obj)) {
Object.preventExtensions(obj);
}
obj.like = "编程";
console.log(obj); // {name: '柏拉图', age: 23}
-
原理(Polyfill)
Object.prototype.propertyIsEnumerable()
语法
返回值
应用场景
原理(Polyfill)
Object.seal()
**Object.seal()**方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置(不可配置那么也就不可删除该属性 )。当前属性的值只要原来是可写的就可以改变。
语法
Object.seal(obj)
- ojb: 将要被密封的对象。
返回值
被密封的对象。
应用场景
-
密封对象
const obj = {
name: "柏拉图",
age: 23,
};
Object.seal(obj);
obj.like = "编程"; // 已密封对象不可添加新属性,添加失效
obj.name = "柏拉图修改"; // 已密封对象可修改属性,修改成功
delete obj.name; // 已密封对象不可删除属性,删除失效
console.log(obj);
Object.defineProperty(obj,'name',{ // 尝试为密封对象的属性重新配置描述符,失败
value:'柏拉图精确管理属性',
writable:true,
enumerable:true,
configurable:true
})
console.log(obj);
经典问题
-
如何使对象变得不可扩展?有几种方法可以实现
-
通过
Object.seal(obj)
变得不可扩展const obj = {
name: "柏拉图",
age: 23,
};
if (Object.isExtensible(obj)) {
Object.seal(obj);
}
obj.like = "编程";
console.log(obj); // {name: '柏拉图', age: 23} -
通过
Object.freeze()
变得不可扩展const obj = {
name: "柏拉图",
age: 23,
};
if (Object.isExtensible(obj)) {
Object.freeze(obj);
}
obj.like = "编程";
console.log(obj); // {name: '柏拉图', age: 23} -
通过
Object.preventExtensions(obj)
变得不可扩展const obj = {
name: "柏拉图",
age: 23,
};
if (Object.isExtensible(obj)) {
Object.preventExtensions(obj);
}
obj.like = "编程";
console.log(obj); // {name: '柏拉图', age: 23}
-
原理(Polyfill)
Object.setPrototypeOf()
语法
返回值
应用场景
原理(Polyfill)
Object.prototype.toLocaleString()
语法
返回值
应用场景
原理(Polyfill)
Object.prototype.toString()
toString()
方法返回一个表示该对象的字符串。该方法旨在重写(自定义)派生类对象的类型转换的逻辑。
语法
console.log({}.toString()); // [object Object]
console.log({ a:1 }.toString()); // [object Object]
返回值
一个表示该对象的字符串, 返回的字符串内容如下:
[object Object]
应用场景
-
场景一、各个数据类型重写或覆盖
Object.prototype.toString()
-
场景二、各个数据类型返回各自的
Symbol.toStringTag
或者标签-
原理:
Object.prototype.toString()
返回"[object Type]"
,这里的Type
是对象的类型。如果对象有Symbol.toStringTag
属性,其值是一个字符串,则它的值将被用作Type
。许多内置的对象,包括Map
和Symbol
,都有Symbol.toStringTag
。一些早于ES6
的对象没有Symbol.toStringTag
,但仍然有一个特殊的标签。它们包括(标签与下面给出的类型名相同):Array
Function
Error
Boolean
Number
String
Date
RegExp
-
注意: 如果对象有
Symbol.toStringTag
属性,对象可以通过定义Symbol.toStringTag
属性来更改Object.prototype.toString()
的行为,从而导致意想不到的结果 -
尝试:
-
返回
Number
的Symbol.toStringTag
或者特殊标签const value = 1;
const reg = /^\[object\s+(.*)\]$/;
console.log(Object.prototype.toString.call(value)) // [object Number]
const type = reg.exec(Object.prototype.toString.call(value))?.[1];
console.log(type); // Number
value[Symbol.toStringTag] = "NumberEdit"; // Number 没有 Symbol.toStringTag,但是有一个特殊的标签 “Number” , 所以不会发生重写 Symbol.toStringTag 的情况
console.log(Object.prototype.toString.call(value)) // [object Number] -
返回
String
的Symbol.toStringTag
或者特殊标签const value = "哈哈";
const reg = /^\[object\s+(.*)\]$/;
console.log(Object.prototype.toString.call(value)) // [object String]
const type = reg.exec(Object.prototype.toString.call(value))?.[1];
console.log(type); // String
value[Symbol.toStringTag] = "NumberEdit"; // String 没有 Symbol.toStringTag,但是有一个特殊的标签 “String”, 所以不会发生重写 Symbol.toStringTag 的情况
console.log(Object.prototype.toString.call(value)) // [object String] -
返回
Boolean
的Symbol.toStringTag
或者特殊标签const value = true;
const reg = /^\[object\s(.*)\]$/;
console.log(Object.prototype.toString.call(value)) // [object Boolean]
const type = reg.exec(Object.prototype.toString.call(value))?.[1];
console.log(type); // Boolean
value[Symbol.toStringTag] = "NumberEdit"; // Boolean 没有 Symbol.toStringTag,但是有一个特殊的标签 “Boolean”, 所以不会发生重写 Symbol.toStringTag 的情况
console.log(Object.prototype.toString.call(value)) // [object Boolean] -
返回
undefined
的Symbol.toStringTag
或者特殊标签const value = undefined;
const reg = /^\[object\s+(.*)\]$/;
console.log(Object.prototype.toString.call(value)) // [object Undefined]
const type = reg.exec(Object.prototype.toString.call(value))?.[1];
console.log(type); // Undefined -
返回
null
的Symbol.toStringTag
const value = null;
const reg = /^\[object\s+(.*)\]$/;
console.log(Object.prototype.toString.call(value)) // [object Null]
const type = reg.exec(Object.prototype.toString.call(value))?.[1];
console.log(type); // Null -
返回
object
的Symbol.toStringTag
或者特殊标签const value = {};
const reg = /^\[object\s+(.*)\]$/;
console.log(Object.prototype.toString.call(value)) // [object Object]
const type = reg.exec(Object.prototype.toString.call(value))?.[1];
console.log(type); //Object
value[Symbol.toStringTag] = "NumberEdit"; // Object 有 Symbol.toStringTag, 所以会发生重写 Symbol.toStringTag 的情况
console.log(Object.prototype.toString.call(value)) // [object NumberEdit] -
返回
Array
的Symbol.toStringTag
const value = [];
const reg = /^\[object\s+(.*)\]$/;
console.log(Object.prototype.toString.call(value)) // [object Array]
const type = reg.exec(Object.prototype.toString.call(value))?.[1];
console.log(type); //Array
value[Symbol.toStringTag] = "NumberEdit"; // Array 有 Symbol.toStringTag, 所以会发生重写 Symbol.toStringTag 的情况
console.log(Object.prototype.toString.call(value)) // [object NumberEdit] -
返回
Date
的Symbol.toStringTag
const value = new Date();
const reg = /^\[object\s+(.*)\]$/;
console.log(Object.prototype.toString.call(value)) // [object Date]
const type = reg.exec(Object.prototype.toString.call(value))?.[1];
console.log(type); //Date
value[Symbol.toStringTag] = "NumberEdit"; // Date 有 Symbol.toStringTag
console.log(Object.prototype.toString.call(value)) // [object NumberEdit] -
返回
RegExp
的Symbol.toStringTag
const value = /a/;
const reg = /^\[object\s+(.*)\]$/;
console.log(Object.prototype.toString.call(value)) // [object RegExp]
const type = reg.exec(Object.prototype.toString.call(value))?.[1];
console.log(type); //RegExp
value[Symbol.toStringTag] = "NumberEdit"; // RegExp 有 Symbol.toStringTag
console.log(Object.prototype.toString.call(value)) // [object NumberEdit]
-
-
-
场景三、自定义对象如何获得
[object MyObject]
类型解决方案: 更改原型上的
[Symbol.toStringTag]
属性即可function Person(){
}
Person.prototype[Symbol.toStringTag] = "Person";
const person = new Person();
console.log(Object.prototype.toString.call(person)); -
场景四、
Object.prototype.toString.call(Boolean.prototype)
结果是什么?
原理(Polyfill)
Object.prototype.valueOf()
Object
的 valueOf()
方法将 this
值转换为一个对象。此方法旨在用于自定义类型转换的逻辑时,重写派生类对象。
语法
object.valueOf()
返回值
返回 this
值本身,如果尚未转换为对象,则转换为对象。因此它的返回值将从不会被任何原始值转换算法使用。
const obj = { foo: 1 };
console.log(obj.valueOf() === obj); // true
应用场景
-
场景一、各个数据类型继承、重写、覆盖
valueOf
原理(Polyfill)
Object.values()
语法
返回值
应用场景
原理(Polyfill)