对象,我遇见了你

2023-11-10

什么是对象

生活中,我们经常会听到对象两个字,你对象呢、你谈对象了吗?诸如此类~~
在工作中,我们依然逃不了面对对象的问题,那什么是对象呢?
对象是一个人?没错,你就是一个对象。
对象是一个物体?没错,那个物体就是一个对象。
对象是一个电影?没错,电影也是一个对象。
啥???怎么什么都是一个对象。没错,世间万物都可以看作是一个对象,对象是一个抽象的概念,可以用来概括你描述物体的属性和方法,在生活中,比如:汽车是一个对象,汽车有颜色、大小、重量等属性,方法有启动、停止等,在工作中,可以把某一类规划为一个对象,我们可以把这个类的属性和方法规划到这个对象上

对象属性

Object.assign()

 1.1 浅拷贝对象 相同的值会被覆盖为新值
 1.2 参数1为接受拷贝的对象,参数2为传递拷贝的对象
 1.3 结果会改变第一个参数对象,同时会返回这个参数对象
```javascript
var aaa = { 'a': 1, 'b': 2 }
var bbb = { 'b': 3, 'c': 4 }
var ccc = { ...aaa, ...bbb }
console.log(aaa)  // {"a":1,"b":2}
console.log(bbb)  // {"b":3,"c":4}
console.log(ccc)  // {"a":1,"b":3,"c":4}

console.log('----------------------')

const target = { a: 1, b: 2 }
const source = { b: 3, c: 4 }
const result = Object.assign(target, source)
console.log(target)  //  { a: 1, b: 3, c: 4 }
console.log(source)  //  {"b":3,"c":4}
console.log(result)  //  {"a":1,"b":3,"c":4}
console.log(target === result) // true
console.log(source === result) // false

```

注意:如果是扩展运算符就不会影响到原对象,如果是Object.assign会把对象和新对象都执行新的内存地址,会被修改为新对象

Object.create()

1.1 创建一个新对象,新对象继承原来创建的对象
1.2 Object.create() 是一个深拷贝
1.3 Object.create于传统创建对象的区别是在新旧对象之间增加了一层,这样引用地址就是解耦的 obj === newObj 是false 新旧对象之间就互不影响
```javascript
var aaa = {
  a: 1,
  b: 2,
  c: {
    d: 3,
    e: 4
  }
}

var bbb = Object.create(aaa)
console.log(aaa)  // {"a":1,"b":2,"c":{"d":3,"e":4}}
console.log(bbb)  // {}
console.log(bbb.a)  // 1
bbb.a = 2 
console.log(aaa) // {"a":1,"b":2,"c":{"d":3,"e":4}}
console.log(bbb)  // {"a":2}
```
Object.create()  可应用于继承
```javascript
function Person(name) {
  this.name = name;
  this.permission = ["user", "salary", "vacation"];
}

Person.prototype.say = function () {
  console.log(`${this.name} 说话了`);
};

function Staff(name, age) {
  Person.call(this, name);
  this.age = age;
}

Staff.prototype = Object.create(Person.prototype, {
  constructor: {
      // 若是不将Staff constructor指回到Staff, 此时的Staff实例		     zs.constructor则指向Person
      value: Staff,
  },
});

Staff.prototype.eat = function () {
  console.log("吃东西啦~~~");
};
```

Object.is()

 1.1 用于判断两个对象是不是一致
```javascript
Object.is('foo', 'foo') // true
Object.is([], []) // false

Object.is(null, null) // true
Object.is(NaN, NaN) // true

// 特别的:
Object.is(0, -0)            // false
Object.is(+0, -0)           // false
Object.is(0, +0)            // true
Object.is(-0, -0)           // true
Object.is(NaN, 0/0)         // true

```

Object.keys()、Object.values()、Object.entries()、Object.fromEntries()

1.1 获取对象的键、值、键值对、键值对数组转化为对象
```javascript
let obj = {
name: ‘ruovan’,
age: 24
}

console.log(Object.keys(obj)) // ["name","age"]
console.log(Object.values(obj)) // ["ruovan",24]
console.log(Object.entries(obj)) // [["name","ruovan"],["age",24]]

let arr = Object.entries(obj)
console.log(Object.fromEntries(arr)) // {"name":"ruovan","age":24}
```

Object.toString()、Object.toLocaleString()

1.1  对象字符串(每一个对象都有这个方法)

1.2 使用toLocaleString可以将对象根据语言环境来转换字符串
```javascript
let date = new Date()

console.log(date.toString()) //  Fri Apr 07 2023 17:11:04 GMT+0800 (中国标准时间)
console.log(date.toLocaleString()) //  2023/4/7 17:11:04

let num = 123456789
num.toLocaleString() // '123,456,789'


let obj = { a: 1, b: 2 }
let arr = [1,2,3]
let str = '123'

obj.toString() // [object Objetc]
arr.toString() // 1,2,3
str.toString() // 123
```

Object.getPrototypeOf()、 Object.setPrototypeOf()、Object.prototype.isPrototypeOf()

1.1 Object.getPrototypeOf()  用于返回指定对象的原型,如果没有则是null
1.2 Object.setPrototypeOf()  用于设置指定对象的原型
1.3 Object.prototype.isPrototypeOf()  用于检测一个对象是否存在于另一个对象的原型链上
```javascript
let obj = {
  name: 'zs',
  age: 20
}

console.log(Object.getPrototypeOf(obj)) // true
console.log(Object.getPrototypeOf(obj) === obj.__proto__) // true
console.log(Object.getPrototypeOf(Object) === Function.prototype) // true

/***
 * getPrototypeOf 作用和 __proto__ 效果一样  但是 __proto__有兼容性问题 在生产环境下 还是用 getPrototypeOf
 * Object 也是构造函数, 因此,返回的是函数的原型对象
 */

console.log('------获取原型-------')

function PersonObj(name, age) {
  this.name = name
  this.age = age
}


function testObj(like) {
  this.like = like
}


PersonObj.prototype.say = function () {
  console.log(this.name + '说话了')
}

const person1 = new PersonObj('zs', 20)
console.log(Object.getPrototypeOf(person1)) // {}
console.log(person1.__proto__) // {}


Object.setPrototypeOf(person1, testObj)

console.log(Object.getPrototypeOf(person1)) 
// function testObj(like){
//   this.like = like
// }


console.log('----设置原型------')


let obj1 = {}
let obj2 = new Object()

console.log(obj1.__proto__.isPrototypeOf(obj2)) // true

/**
 * isPrototypeOf 检测一个对象是不是另一个对象的实例
 * 类似方法还有 instanceof A instanceof B
 */
```

Object.freeze()、Object.isFrozen()、Object.preventExtensions()、Object.seal()、Object.isExtensible()

1.1 Object.freeze()可用于冻结一个对象,冻结后,该对象的所有属性、方法均不可修改
1.2 Object.freeze() 冻结是一个浅对象,对象里面的对象可以修改
1.3 被冻结的对象不能被解冻,只能重新定义一个对象再操作
1.4 可利用Object.freeze()来提升性能
1.5 Object.freeze()是所有的属性只读,不能修改
1.6 Object.preventExtensions()对象不可扩展,即不可新增属性和方法。但可以修改和删除
1.7 Object.seal()对象可以修改,不能删除
1.8 Object.isFrozen() 判读对象有没有被冻结
1.9 Object.isExtensible()对象可扩展,可新增属性和方法,一般与Object.preventExtensions() 一起用

	var obj = {
	  a: 1,
	  b: 2,
	  c: {
	    aa: 11,
	    bb: 22
	  }
	}
	Object.freeze(obj)
	console.log(Object.isFrozen(obj)) // 是否冻结对象
	obj.c.aa = 33
	obj.a = 0
	console.log(obj) // 浅冻结 {"a":1,"b":2,"c":{"aa":33,"bb":22}}
	var bbb = Object.assign({}, obj) //解冻对象
	bbb.a = 0
	console.log(bbb) // {"a":0,"b":2,"c":{"aa":33,"bb":22}}
	console.log('-------freeze---------')
	var obj1 = {
	  a: 1,
	  b: 2,
	  c: {
	    aa: 11,
	    bb: 22
	  }
	}
	Object.seal(obj1) // 对象只能修改 不能删除
	
	obj1.a = 2
	delete obj.b
	console.log(obj1) // {"a":2,"b":2,"c":{"aa":11,"bb":22}}
	
	console.log('-----seal-----')
	
	var obj2 = {
	  a: 1,
	  b: 2,
	  c: {
	    aa: 11,
	    bb: 22
	  }
	}
	Object.preventExtensions(obj2) //不可新增 可编辑和删除
	obj2.a = 11
	delete obj2.b
	obj2.d = 000
	console.log(obj2) // {"a":11,"c":{"aa":11,"bb":22}}

在vue2中,双向绑定的原理就是利用了 Object.defineProperty ,vue实例化的对象,vue将遍历此对象所有的属性,把这些属性全部转化为getter和setter,在属性被访问和修改的时候来通知变化。但如果遇到 Object.freeze()来冻结了对象,将不会为改对象加上getter和setter等数据劫持的方法。性能提升效果对比如下:
比如我们渲染一个1000*10的表格,开启Object.freeze对比
在这里插入图片描述为什么Object.freeze() 的性能会更好?
在这里插入图片描述

Object.freeze() 可提升性能,如果在操作大数据量的时候,如果确定这个数据量后期不会被改动,可冻结该数据,可大幅度的提升性能

Object.hasOwn () 、Object.prototype.hasOwnProperty()

1.1 这两个方法都是来检测对象上有没有属性,均是只能检测静态属性,不能检测继承属性
1.2 Object.hasOwn() 是 Object.prototype.hasOwnProperty()的替代方案,现在一般用Object.hasOwn()

let obj = {
  foo: '222'
}

console.log(Object.hasOwn(obj, "foo")) // true
console.log(Object.hasOwn(obj, "foo1")) // false
console.log(Object.hasOwn(obj, 'toString')) // false
console.log(obj.hasOwnProperty("foo")) // true
console.log(obj.hasOwnProperty("foo1")) // false
console.log(obj.hasOwnProperty('toString')) // false

为什么用 Object.hasOwn() 来替代 Object.hasOwnProperty() ,Object.hasOwnProperty() 是原型上面的方法,当对象的原型被改了之后,这个方法就能用了,于是就给对像自己定义了一个方法,其功能与Object.hasOwnProperty() 一样

Object.defineProperty()、Object.defineProperties()、Object.getOwnPropertyDescriptor()、Object.getOwnPropertyDescriptors()、Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()

1.1 Object.defineProperty()会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
1.2 Object.defineProperties()是Object.defineProperty()复写形式
1.3 Object.getOwnPropertyDescriptor()返回指定对象上一个自有属性对应的属性描述符(自有属性即静态属性,不需要从原型链上进行查找)
1.4 Object.getOwnPropertyDescriptors()方法用来获取一个对象的所有自身属性的描述符
1.5 Object.getOwnPropertyNames() 方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性)组成的数组
1.6 Object.getOwnPropertySymbols() 方法返回一个给定对象自身的所有 Symbol 属性的数组

let Person = {}
let value = ''
Object.defineProperty(Person, 'name', {
  // value: 'jack',
  // writable: true, // 是否可以改变
  enumerable: true, // 是否可以枚举,
  configurable: true, // 是否可配置
  set(val) {
    value = val
  },
  get() {
    return value
  }
})

Person.name = "rose"; // 当writable是false 是{"name":"jack"} 当时true时  是{"name":"rose"}
console.log(Person) // 当enumerable是false 是空对象 当时true时  是{"name":"rose"}
delete Person.name // 无法删除  configurable是true才可删除 

console.log('--------Object.defineProperty()------')

var obj3 = {};
Object.defineProperties(obj3, {
  'property1': {
    value: true,
    writable: true
  },
  'property2': {
    value: 'Hello',
    writable: false
  }
})

console.log('--------Object.defineProperties()------')


const object1 = {
  property1: 42,
  property2: 42
};

var a = Symbol("a");
var b = Symbol.for("b");

object1[a] = "localSymbol";
object1[b] = "globalSymbol";

const descriptor1 = Object.getOwnPropertyDescriptor(object1, 'property1');
console.log(descriptor1) // {"value":42,"writable":true,"enumerable":true,"configurable":true}
const descriptor2 = Object.getOwnPropertyDescriptors(object1);
console.log(descriptor2) // {"property1":{"value":42,"writable":true,"enumerable":true,"configurable":true},"property2":{"value":42,"writable":true,"enumerable":true,"configurable":true}}
const descriptor3 = Object.getOwnPropertyNames(object1);
console.log(descriptor3) // ["property1","property2"]
const descriptor4 = Object.getOwnPropertySymbols(object1);
console.log(descriptor4) // [Symbol(a), Symbol(b)]

deep clone

```javascript
function deepClone(obj) {
  let newObj = {}
  for (let key in obj) {
    let item = obj[key]
    if (Object.prototype.toString.call(item) === '[object Object]') {
      newObj[key] = deepClone(item)
    } else {
      newObj[key] = obj[key]
    }
  }
  return newObj
}

var aaaa = {
  a: 1,
  b: 2,
  c: {
    d: 3,
    e: 4
  }
}
var bbbb = deepClone(aaaa)

bbbb.a = 11
console.log(aaaa.a)  // 1
console.log(bbbb.a) // 11
console.log(bbbb) // {"a":11,"b":4,"c":{"d":3,"e":4}}
```

对象defineProperty 与 Proxy代理对象区别

Proxy对象用于创建一个对象的代理,是用于监听一个对象的相关操作。代理对象可以监听我们对原对象的操作
在实例化Proxy对象时,get方法用来获取对象属性,set方法用来设置对象属性

const object = {
  name: 'zhangsan'
}

const objProxyPrototype = {
  count: 2
}

const objProxy = new Proxy(object, {
  get(target, key) {
    console.log('获取属性')
    return target[key]
  },
  set(target, key, val) {
    console.log('设置属性')
    target[key] = val
  },
  has(target, key) {
    return !!target[key]
  },
  getPrototypeOf(target) {
    // return Object.getPrototypeOf(target)
    return objProxyPrototype
  },
  isExtensible(target) {
    return Object.isExtensible(target);
  },
  preventExtensions(target) {
    return Object.preventExtensions(target);
  }
})

console.log(objProxy.name)

objProxy.name = 'lisi'
console.log('name' in objProxy) // true
console.log('age' in objProxy) // false

console.log(Object.getPrototypeOf(objProxy)) // {"count":2}
console.log(Object.getPrototypeOf(objProxy) === objProxyPrototype) // true
console.log(Object.isExtensible(objProxy)) // true

Object.preventExtensions(objProxy);
console.log(Object.isExtensible(objProxy)) // false

proxy代理对象内部并没有对代理的对象进行this拦截,因此不能保证与内部对象this一致。如下:

const obj={
 name:'_island',
 foo:function(){
   return this === objProxy
 }
}

const objProxy=new Proxy(obj,{})
console.log(obj.foo()); // false
console.log(objProxy.foo()); // true

vue2中双向绑定的原理是利用Object.defineProperty() 来实现的,而vue3中是利用Proxy代理来实现的。那为什么在vue3中要对这块进行优化呢???
我们在用vue2的时候,有没有遇到一个问题,当我们的数据明明发生了变化,但是为什么页面没有更新呢??? 因为 Object.defineProperty 设计的初衷并不是为了去监听拦截一个对象,它也实现不了更加丰富的操作,比如新增、删除等操作,所以我们在操作数据的时候,明明数据变化了,但是Object.defineProperty监听不到改变,我们的DOM就不会进行更新,在vue3中,我们的尤大大就用Proxy进行了优化

对象原型链

在介绍对象属性的时候,经常会用到自有属性(静态属性)、继承属性等
自有属性是对象自己的属性
继承属性是不是对象自己的属性,但是又可以用的属性,是继承过来的,就像你是一个富二代,明明你自己没有挣到钱,但依然有花不完的钱一样
每一个对象都会有一个原型对象,原型对象上有一些属性和方法,那这个对象的实例方法就继承了这个对象的原型对象上的属性和方法。
感兴趣的宝们可以去查下原型链。这里不做多的介绍了。。。
原型链图如下:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对象,我遇见了你 的相关文章

随机推荐

  • 08-分布式

    1 分布式中 接口的幂等性的设计 在高并发场景的架构里 幂等性是必须得保证的 比如说提交作业 查询和删除不在 幂等讨论范围 1 建唯一索引id 每次操作 都根据操作和内容生成唯一的id 在执行之前先判断id是否存在 如果不存在 则 执行后续
  • rem的使用方式

    rem是什么 rem是指相对于根元素的字体大小的单位 在日常开发过程中我们通常把根元素 html body 的字体设置为10px 方便于我们计算 此时子元素的1rem就相当于10px rem与em的区别 各自的优缺点 em子元素字体大小的e
  • CVPR 2019 论文大盘点—人体姿态篇

    CV君盘点了CVPR 2019 中有关人体姿态的论文 其中研究 3D人体姿态估计的论文最多 有 11 篇 研究 2D 姿态估计的 7 篇 姿态迁移 2 篇 人体图像生成 1 篇 人体捕捉 2 篇 另外还有2篇创建了新的基准数据集 姿态估计是
  • python云图

    安装相关插件 python3 m pip install jieba wordcloud matplotlib import matplotlib pyplot as plt import jieba from wordcloud impo
  • 【Spring Boot】【前后端分离】后端接口返回结果统一封装

    文章目录 创建 SpringBoot 项目 封装返回结果 实现返回对象的自动封装 处理异常 测试 最近在尝试使用前后端分离的模式写一个简单的个人博客 遇到接口数据返回结构的问题 在网上查了一圈 发现了一个很好用的方法 在复现的过程中也遇到了
  • 算法设计与分析课后总结

    算法设计与分析课后总结 算法设计与分析 第1章 算法设计基础 课后习题 第二章算法分析基础 课后习题 1 考虑下面算法 回答下列问题 算法完成什么功能 算法的基本语句时什么 基本语句执行了多少次 2 分析以下程序段中基本语句的执行次数 要求
  • 100天精通Python(可视化篇)——第92天:Pyecharts绘制炫酷柱状图、条形图实战大全

    文章目录 专栏导读 1 基础柱状图 2 旋转x轴标签 3 旋转坐标轴 4 添加坐标轴名称 5 添加标记点 6 添加标注线 7 添加数据 8 添加自定义背景图 9 堆叠柱状图 10 柱状图与折线图组合 11 三维柱状图 12 水平滑动 鼠标滚
  • 包、模块、函数的关系结构

    三者关系 python中程序的结构是由包 模块 函数 类大致构成 其关系如下 package module function 模块定义与调用 1 python中一个 py文件都可以是一个module module可以有函数 类 代码组成 如
  • 使用python解决中英混合参考文献中et al 和等的问题

    这个代码使用zipfile将docx进行解压 然后操作document xml文件 找到中文中的et al之后替换为 等 然后再压缩为docx import zipfile import re import os import shutil
  • curl服务器文件,curl 向远程服务器传输file文件

    public function upload 获取上传文件信息 文件名称以自己实际上传文件名称为准 fileinfo FILE filename 请求参数 依据商户自己的参数为准 requestParam version requestPa
  • 声网(agora)音视频通话sdk—微信小程序demo

    首先需要注册一个声网账号 注册成功后创建项目 appid是指声网项目的appid 后续会在小程序的配置文件中用到 微信小程序接入视频通话 需要声网给开通小程序的权限 给声网邮箱发送邮件 注明开通微信小程序接入权限 并给发送appid app
  • Python代码扫描:企业级代码代码安全漏洞扫描Bandit

    目录 什么是Bandit 特点 安装 配置 配置Bandit Pycharm配置外置工具 使用实践 命令行参数 检查单个文件 检查整个目录 PyCharm中对单个文件或者项目目录的扫描 一个使用案例 应用场景 总结 参考资料 注意 后续技术
  • js DOM

    DOM Document Object Model HTML 和 XML 文档的编程接口 通过 DOM JavaScript 能够访问和改变 HTML 文档的所有元素 1 查找 通过 id 查找 HTML 元素 div div 2 通过标签
  • Paper and Codes Leaderboard

    目录 介绍 模型入选标准 1 目标检测 Paper and Codes for COCO by 2023 3 31 COCO FPS Models by 2023 02 18 Look at Batch Size 2 图像分类 ImageN
  • 【Backbone: MLP-Mixer】MLP-Mixer: An all-MLP Architecture for Vision

    Abstract CNN和attention based结构很棒 但不是必须的 本文提出MLP Mixer 一种基于多层感知机 MLPs 的框架 包含两种layers 1 channel mixing MLPs 应用在image patch
  • C++(30)——lambda表达式原理及应用

    lambda lambda这个词起源于数学上的 在C 中利用lambda表达式 可以方便的定义和创建匿名函数 lambda可以看做函数对象的升级版 改进了函数对象以下的缺点 使用在泛型算法中的参数传递的过程中 比较性质 自定义操作 优先级队
  • J2EE之自定义MVC框架知识(中篇)

    J2EE之自定义MVC框架知识 中篇 文章目录 J2EE之自定义MVC框架知识 中篇 前言 1 优化中央控制器中的action容器 使其加载变成可配置的 1 1 编写 xml文件 config xml 1 2 导入XML建模相关的类 Act
  • INNO setup 制作安装包

    1 获取SQLserver安装路径vardbpath string rtn boolean rtn RegQueryStringValue HKEY LOCAL MACHINE SOFTWAREMicrosoftMSSQLServerSet
  • 95-38-150-Buffer-CompositeByteBuf

    文章目录 1 概述 2 继承关系 1 概述 CompositeByteBuf实际就是个ByteBuf的包装器 它将多个ByteBuf组合成一个集合 然后对外提供统一的ByteBuf接口 2 继承关系
  • 对象,我遇见了你

    对象 什么是对象 对象属性 Object assign Object create Object is Object keys Object values Object entries Object fromEntries Object t