百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

对象 (基础详解)_对象的基本概念和主要特征

myzbx 2025-08-31 06:13 44 浏览

创建对象的方式

(1)Object 构造函数方式 Object 构造函数将给定的值包装为一个新对象。

  • 如果给定的值是 null 或 undefined, 它会创建并返回一个空对象。
  • 否则, 它将返回一个和给定的值相对应的类型的对象。
  • 如果给定值是一个已经存在的对象, 则会返回这个已经存在的值( 相同地址)
let o = new Object()
  o.foo = 42
  console.log(o)

(2)对象字面量方式

var obj1 = { foo: 'bar', x: 42 };

(3)Object.create() 方法用于创建一个新对象,使用现有的对象来作为新创建对象的原型(prototype)。

如果该参数被指定且不为 undefined,则该传入对象的自有可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符。这些属性对应于 Object.defineProperties() 的第二个参数。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create

const person = {
       isHuman: false,
       printIntroduction: function() {
           console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
       }
   };

   const me = Object.create(person);
   console.log(me)
   me.name = 'Matthew'; // "name" is a property set on "me", but not on "person"
   me.isHuman = true; // inherited properties can be overwritten

   me.printIntroduction();
   // expected output: "My name is Matthew. Am I human? true"

对象的静态方法

Object.assign() 通过复制一个或多个对象来创建一个新的对象。

Object.create() 使用指定的原型对象和属性创建一个新对象。

Object.defineProperty() 给对象添加一个属性并指定该属性的配置。

Object.defineProperties() 给对象添加多个属性并分别指定它们的配置。

Object.entries() 返回给定对象自身可枚举属性的 [key, value] 数组。

Object.freeze() 冻结对象:其他代码不能删除或更改任何属性。


Object.getOwnPropertyDescriptor() 返回对象指定的属性配置。


Object.getOwnPropertyNames() 返回一个数组,它包含了指定对象所有的可枚举或不可枚举的属性名。


Object.getOwnPropertySymbols() 返回一个数组,它包含了指定对象自身所有的符号属性。 Object.getPrototypeOf() 返回指定对象的原型对象。

Object.is() 比较两个值是否相同。所有 NaN 值都相等(这与==和===不同)。

Object.isExtensible() 判断对象是否可扩展。

Object.isFrozen() 判断对象是否已经冻结。

Object.isSealed() 判断对象是否已经密封。

Object.keys() 返回一个包含所有给定对象自身可枚举属性名称的数组。

Object.preventExtensions() 防止对象的任何扩展。

Object.seal() 防止其他代码删除对象的属性。

Object.setPrototypeOf() 设置对象的原型(即内部 [[Prototype]] 属性)。

Object.values() 返回给定对象自身可枚举值的数组。

对象的实例实例属性

  • Object.prototype.constructor
  • 一个引用值,指向 Object 构造函数
  • Object.prototype.__proto__
  • 指向一个对象,当一个 object 实例化时,使用该对象作为实例化对象的原型

方法定义

对象属性也可以是一个函数、getter、setter方法。

var o = {
 property: function ([parameters]) {},//or   property([parameters]) {}


 get property() {},
 set property(value) {},
};

属性

对象拥有两种属性:数据属性和访问器属性

数据属性

数据属性是键值对,并且每个数据属性拥有下列特性:

configurable :当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认值为false

Value: 包含这个属性的数据值。

Writable:如果该值为 false,则该属性的Value 特性不能被修改。

Enumerable : 如果该值为 true,则该属性可以用 for...in 循环来枚举。

let obj = {
        foo: 123
    };
    console.log(Object.getOwnPropertyDescriptor(obj, 'foo'))

访问器属性

访问器属性有一个或两个访问器函数(getset)来存取数值。 自定义 Setters和getter

function Archiver() {
 var temperature = null;
 var archive = [];

 Object.defineProperty(this, 'temperature', {
   get: function() {
     console.log('get!');
     return temperature;
   },
   set: function(value) {
     temperature = value;
     archive.push({ val: temperature });
   }
 });

 this.getArchive = function() { return archive; };
}

var arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;
arc.temperature = 13;
arc.getArchive(); // [{ val: 11 }, { val: 13 }]

可枚举性

对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。
Object.getOwnPropertyDescriptor
方法可以获取该属性的描述对象

可枚举属性是指那些内部 “可枚举” 标志设置为 true 的属性,对于通过直接的赋值和属性初始化的属性,该标识值默认为即为 true,对于通过 Object.defineProperty 等定义的属性,该标识值默认为 false

    var o = {};
   Object.defineProperty(o, "a", {
       value: 1,
       enumerable: true
   });
   Object.defineProperty(o, "b", {
       value: 2,
       enumerable: false
   });
   Object.defineProperty(o, "c", {
       value: 3
   }); // enumerable 默认为 false
   console.log(o)

   for (var i in o) {
       console.log(i)
   }
let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')
//  {
//    value: 123,
//    writable: true,
//    enumerable: true,
//    configurable: true
//  }

for ...in

for...in语句以任意顺序迭代一个对象的除Symbol以外的可枚举属性,包括继承的可枚举属性。

  const user = {};
   Object.prototype.authenticated = true;
   for (var i in user) {
       console.log(i)
   }

示例2

 var obj = {};
    obj.name = 'xkx';
    obj.age = 18;
    obj.run = function() { //创建一个 run()方法并返回值
        return this.name + this.age + '运行中...';
    };

    // 给原型添加属性和方法
    Object.prototype.gaga = function() {
        console.log('gaga')
    }
    Object.prototype.names = 'names'
        // 给原型添加一个可枚举的属性
    Object.defineProperty(Object.prototype, "ages", {
        enumerable: false,
        configurable: false,
        writable: false,
        value: 20
    });
    var descriptor = Object.create(null); // 没有继承的属性
    // descriptor.value = 'static';
    // // 默认没有 enumerable,没有 configurable,没有 writable
    // Object.defineProperty(obj, 'key', descriptor);
    // console.log(Object.getOwnPropertyDescriptor(obj, 'key'))


    //显式

    Object.defineProperty(obj, "key", {
        enumerable: false,
        configurable: false,
        writable: false,
        value: "static"
    });
    console.log(Object.getOwnPropertyDescriptor(obj, 'key'))
    console.log(obj)
    console.log(Object.getPrototypeOf(obj))

    for (var i in obj) {
        console.log(i)
    }

原型上添加的不可枚举的ages属性,没有被枚举

如果将enumerable 改为true,原型上添加的ages 可枚举属性被遍历

Object.defineProperty(Object.prototype, "ages", {
        enumerable: true,
        configurable: false,
        writable: false,
        value: 20
    });

创建属性

如果对象中不存在指定的属性,Object.defineProperty() 会创建这个属性。当描述符中省略某些字段时,这些字段将使用它们的默认值。

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

var o = {}; // 创建一个新对象

// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(o, "a", {
  value : 37,
  writable : true,
  enumerable : true,
  configurable : true
});

getPrototypeOf方法

getPrototypeOf()是JavaScript中的内置函数,用于检查用户创建的对象的原型。大多数时候,它用于检查两个对象是否具有相同的原型。这里的原型是指用户在JavaScript代码中定义的对象的内部定义

  const person = {
        isHuman: false,
        printIntroduction: function() {
            console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
        }
    };

    const me = Object.create(person);
    console.log(me)
    me.name = 'Matthew'; // "name" is a property set on "me", but not on "person"
    me.isHuman = true; // inherited properties can be overwritten

    me.printIntroduction();
    // expected output: "My name is Matthew. Am I human? true"

    console.log(Object.getPrototypeOf(me))

应用场景: (1)完整克隆一个对象,还拷贝对象原型的属性,可以采用下面的写法。

// 写法一
const clone1 = {
  __proto__: Object.getPrototypeOf(obj),
  ...obj
};

// 写法二
const clone2 = Object.assign(
  Object.create(Object.getPrototypeOf(obj)),
  obj
);

// 写法三
const clone3 = Object.create(
  Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj)
)

getOwnPropertyDescriptor 方法


Object.getOwnPropertyDescriptor
方法可以获取该属性的描述对象。

let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')
//  {
//    value: 123,
//    writable: true,
//    enumerable: true,
//    configurable: true
//  }
 console.log(Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable)
 console.log(Object.getOwnPropertyDescriptor(Object.prototype, 'ages').enumerable)

defineProperty方法

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象

Object.keys(obj)

Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。

 var obj = {};
    obj.name = 'xkx';
    obj.age = 18;
    obj.run = function() { //创建一个 run()方法并返回值
        return this.name + this.age + '运行中...';
    };

    // 给原型添加属性和方法
    Object.prototype.gaga = function() {
        console.log('gaga')
    }
    Object.prototype.names = 'names'
        // 给原型添加一个可枚举的属性
    Object.defineProperty(Object.prototype, "ages", {
        enumerable: true,
        configurable: false,
        writable: false,
        value: 20
    });
    var descriptor = Object.create(null); // 没有继承的属性
    // descriptor.value = 'static';
    // // 默认没有 enumerable,没有 configurable,没有 writable
    // Object.defineProperty(obj, 'key', descriptor);
    // console.log(Object.getOwnPropertyDescriptor(obj, 'key'))


    //显式

    Object.defineProperty(obj, "key", {
        enumerable: true,
        configurable: false,
        writable: false,
        value: "static"
    });
    // console.log(Object.getOwnPropertyDescriptor(obj, 'key'))
    // console.log(obj)
    // console.log(Object.getPrototypeOf(obj))


    // console.log(Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable)
    // console.log(Object.getOwnPropertyDescriptor(Object.prototype, 'ages').enumerable)



    // 查看对象原型上toString
    console.log(Object.getOwnPropertyDescriptor(Object.prototype, 'toString'))
        // 修改前
    console.log(obj.toString())

    // 原型链方式修改
    Object.prototype.toString = function() {
            return '修改了toString方法'
        }
        // defineProperty方式修改
        // Object.defineProperty(Object.prototype, 'toString', {
        //         value: '.........'
        //     })
        // 修改后
    console.log(obj.toString())
        // 修改 重写 对象原型上的toString 方法

    // console.log(Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable)

    for (var i in obj) {
        console.log(i)
    }
    console.log(Object.keys(obj))

可以发现原型上的属性并没有被枚举出来

常用方法

(1) 怎样判断某个对象是否为另一个对象的原型对象 使用
Object.prototype.constructor.prototype进行比较

var obj1 = {name: "李雷"};
var obj2 = {age: 23};
obj1.constructor.prototype === Object.prototype; // true

(2)使用:
Object.prototype.isPrototypeOf()进行比较

var obj1 = {name: "Lilei"};
var obj2 = Object.create(obj1);

obj1.isPrototypeOf(obj2); // true

(3)扩展属性 ECMAScript 提案(第 3 阶段)的剩余/扩展属性将扩展属性添加到对象字面量。它将自己提供的对象的枚举属性复制到一个新的对象上。

使用比Object.assign()更短的语法,可以轻松克隆(不包括原型)或合并对象。

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

var clonedObj = { ...obj1 };
// Object { foo: "bar", x: 42 }

var mergedObj = { ...obj1, ...obj2 };
// Object { foo: "baz", x: 42, y: 13 }

(4)hasOwnProperty 继承的属性不显示

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

function ColoredTriangle() {
  this.color = 'red';
}

ColoredTriangle.prototype = triangle;

var obj = new ColoredTriangle();

for (var prop in obj) {
  if (obj.hasOwnProperty(prop)) {
    console.log(`obj.${prop} = ${obj[prop]}`);
  }
}

// Output:
// "obj.color = red"

(4)Object.create(null)生生的对象里面没有任何属性,非常“空”,我们称它为字典,这种字典对象适合存放数据,不必担心原型带来的副作用。

bject.prototype.isPrototypeOf({}) // true
Object.prototype.isPrototypeOf([]) // true
Object.prototype.isPrototypeOf(/xyz/) // true
Object.prototype.isPrototypeOf(Object.create(null)) // false

关于 _proto和 prototype

而构造函数的prototype是什么,它的原型链最终又指向了哪里呢?这个问题的答案是:函数的prototype是一个在函数声明阶段就会产生的对象(prototype只有函数才会有),这个对象只有两个属性constructor和__proto__,其中__proto__指向了我们原型链的顶点Object.prototype。constructor指向函数本身,里面包括了函数一些基本描述信息比如函数名称,参数个数等。

有意思的是constructor里面即有__proto__又有prototype,他们之间有什么关系和差别呢?首先prototype描述的是原型对象,它是一个实实在在的对象,__proto__是用来描述对象间的关联关系的。最终会指向一个prototype原型。函数由Function衍生而来,所以函数的__proto__指向的是Function.prototype。Function是由Object衍生而来,有意思的事情又发生了,Function的__proto__却并不指向Object.prototype,而是指向Function.prototype这个标准的内置对象。
Function.prototype.__proto__才是指向我们的原型链顶点Object.prototype

Function.proto === Function.prototype // true

相关推荐

如何设计一个优秀的电子商务产品详情页

加入人人都是产品经理【起点学院】产品经理实战训练营,BAT产品总监手把手带你学产品电子商务网站的产品详情页面无疑是设计师和开发人员关注的最重要的网页之一。产品详情页面是客户作出“加入购物车”决定的页面...

怎么在JS中使用Ajax进行异步请求?

大家好,今天我来分享一项JavaScript的实战技巧,即如何在JS中使用Ajax进行异步请求,让你的网页速度瞬间提升。Ajax是一种在不刷新整个网页的情况下与服务器进行数据交互的技术,可以实现异步加...

中小企业如何组建,管理团队_中小企业应当如何开展组织结构设计变革

前言写了太多关于产品的东西觉得应该换换口味.从码农到架构师,从前端到平面再到UI、UE,最后走向了产品这条不归路,其实以前一直再给你们讲.产品经理跟项目经理区别没有特别大,两个岗位之间有很...

前端监控 SDK 开发分享_前端监控系统 开源

一、前言随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的...

Ajax 会被 fetch 取代吗?Axios 怎么办?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天给大家带来的主题是ajax、fetch...

前端面试题《AJAX》_前端面试ajax考点汇总

1.什么是ajax?ajax作用是什么?AJAX=异步JavaScript和XML。AJAX是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实...

Ajax 详细介绍_ajax

1、ajax是什么?asynchronousjavascriptandxml:异步的javascript和xml。ajax是用来改善用户体验的一种技术,其本质是利用浏览器内置的一个特殊的...

6款可替代dreamweaver的工具_替代powerdesigner的工具

dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver...

我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊

接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝...

福斯《死侍》发布新剧照 "小贱贱"韦德被改造前造型曝光

时光网讯福斯出品的科幻片《死侍》今天发布新剧照,其中一张是较为罕见的死侍在被改造之前的剧照,其余两张剧照都是死侍在执行任务中的状态。据外媒推测,片方此时发布剧照,预计是为了给不久之后影片发布首款正式预...

2021年超详细的java学习路线总结—纯干货分享

本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础重点知识点:数据类型、核心语法、面向对象...

不用海淘,真黑五来到你身边:亚马逊15件热卖爆款推荐!

Fujifilm富士instaxMini8小黄人拍立得相机(黄色/蓝色)扫二维码进入购物页面黑五是入手一个轻巧可爱的拍立得相机的好时机,此款是mini8的小黄人特别版,除了颜色涂装成小黄人...

2025 年 Python 爬虫四大前沿技术:从异步到 AI

作为互联网大厂的后端Python爬虫开发,你是否也曾遇到过这些痛点:面对海量目标URL,单线程爬虫爬取一周还没完成任务;动态渲染的SPA页面,requests库返回的全是空白代码;好不容易...

最贱超级英雄《死侍》来了!_死侍超燃

死侍Deadpool(2016)导演:蒂姆·米勒编剧:略特·里斯/保罗·沃尼克主演:瑞恩·雷诺兹/莫蕾娜·巴卡林/吉娜·卡拉诺/艾德·斯克林/T·J·米勒类型:动作/...

停止javascript的ajax请求,取消axios请求,取消reactfetch请求

一、Ajax原生里可以通过XMLHttpRequest对象上的abort方法来中断ajax。注意abort方法不能阻止向服务器发送请求,只能停止当前ajax请求。停止javascript的ajax请求...