js组装知识(待续……)

object.assign()

这个方法回使源对象上的[[Get]]取得属性的值,然后使用目标对象上的[[Set]]设置属性的值
实际上对每个源对象执行的是浅复制,如果多个源对象都有相同的属性,则使用最后一个赋值的值

let obj1 = {get a() {return 'aaa'}
}
let obj2 = {set a(val) {console.log(val)}
}
console.log(obj1.a) //'aaa'// 对象引用
let obj1 = {};
let obj2 = { a:{} }
Object.assign(obj1, obj2)
console.log( obj1.a===obj2.a ) //true// 错误处理
let obj1 = {}
let obj2 = {a: 1,get b() {throw new Error();},c: 3
}
try {Object.assign(obj1, obj2)
} catch (e) {}
console.log(obj1)  //{a:1}
// 因此在抛出错误之前,目标对象上已经完成的修改会继续存在

Object.is()

和===很像,接收两个参数

console.log(+0 === -0) //true
console.log(+0 === 0) //true
console.log(-0 === 0) //true
// 判断NaN
console.log(NaN === NaN)//false
console.log(isNaN(NaN))//true
// 用object.is()轻松解决
console.log(Object.is(NaN, NaN))//true
console.log(Object.is(+0, -0))//false
// 要检查超过两个值,利用递归即可
function deep(x, ...rest) {// 传入的值为 1,[1,1,4];  1,[1,4] ;  1,[4]return Object.is(x, rest[0]) && (rest.length < 2 || deep(...rest))
}
let a = deep(1, 1, 1, 4)
console.log(a) //false

es6增强的对象语法

//1, 属性名简写
let a = 1;
let obj = {a};
console.log(obj) //{a:1}
// 代码压缩程序会在不同的作用域间保留属性名,以防找不到引用   ------这句话还不理解//2,可计算属性
// 有了计算属性,就可以在对象字面量中完成动态属性赋值.中括号运算符包围
//的对象属性键告诉运行时将其作为JavaScript表达式而不是字符串来求职
// 例
const a = 'name';
const b = 'sex';
const c = 'age';
let obj = { [a]: '小红', [b]: '女', [c]: 10 }
console.log(obj)  //{name:'小红',sex:'女',age:10}
// 当然[]里也可以是一个复杂的函数// 3,简写方法名
let obj = {// 旧的写法oldName: function (a) {console.log(a)},//新的写法newName(a) {console.log(a)}
}

解构赋值

// 解构在内部使用ToObject()把源数据结构转换为对象。这也意味着
//在对象结构的上下文中,原始值会被当成对象,这也意味着
// (根据ToObject()的定义),null和undefined不能被结构,否则会抛出错误。
// 例
let { length } = 'foobar';
let { constructor } = 'foobar'
// // 这里一定要切记 源对象转为对象就能看懂了
console.log(length, constructor) //6,ƒ String() { [native code] }
console.log(constructor === String) //true
//嵌套结构
//解构可以使用嵌套结构,以匹配嵌套的属性:
let obj = {name: '小明',age: 11,job: {title: 'web前端'}
}
let { job: { title } } = obj
console.log(title) // web前端
// 参数解构---对参数进行解构不会影响arguments对象
let data = {b: 2, c: 3
}
function aaa(a, { b, c }, d) {console.log(arguments)  // 1,[2,3],4console.log(b, c)       // 2,3
}
aaa(1, data, 2)

try catch 语句

如果try中的代码没有出错,则程序正常运行try中的内容后,不会执行catch中的内容,
如果try中的代码一但出错,程序立即跳入catch中去执行代码,那么try中出错代码后的
所有代码就不再执行了.

try {({ name: p, work: c, job: b } = obj)
} catch (e) {
}
console.log(p, c, b)

工厂函数

这种工厂模式虽然可以解决创建多个类似对象的问题,但没有解
决对象标识问题(即新创建的对象是什么类型)

function createPerson(name, age, sex) {let o = new Object();o.name = name;o.age = age;o.sex = sex;o.say = function () {console.log(`大家好,我的名字叫---${name}`)}return o
}
let p1 = createPerson('小明', 11, '男')
p1.say()
let p2 = createPerson('小红', 10, '女')

构造函数

定义构造函数可以确保实例被标识为特定类型
构造函数也是函数,和普通函数的唯一区别在于调用方式不同

function Person(name, age, sex) {this.name = name;this.age = age;this.sex = sex;this.job = 'web';this.say = function () {console.log(`大家好,我的名字叫---${name}`)}
}
const p3 = new Person('小刚', 11, '男');// 不传参的情况下,可以不加括号,只要有new操作符,就可以调用对应的构造函数

构造函数和工厂函数的区别
1、没有明显的创建对象
2、属性和方法直接赋值给了this
3、没有return

构造函数需要注意的事项?
首字母大写,有助于和普通函数进行区分。

要创建Person实例,需要使用new操作符,以这种方式调用构造函数会进行如下操作。
1> 在内存中创建一个新对象;
2> 这个新对象内部的[[prototype]]特性被赋值为构造函数的prototype属性。
3> 构造函数内部的this被赋值为这个新对象(即this指向新对象)。
4> 执行构造函数内部的代码(给新对象添加属性)
5> 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。 ——————不太明白

原型模式

每个函数都会创建prototype属性,这个属性是一个对象,
包含应该由特定引用类型的实例共享的属性和方法。
好处是 在它上面的属性或方法可以被对象实例共享

console.log(Person.prototype)
Person.prototype.say = function () {console.log(`我是原型上的方法${this.name}`)
}
console.log(p4)

高阶函数

符合以下一个条件即可

  • 若A函数,接收到的参数是一个函数,那么A就可以称之为高阶函数。
  • 若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数
    常见的有Promist setTimeout 、arr.map()……

函数的柯里化

通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式
例 :

function aaa(a){return function bbb(b){return function ccc(c){return a+b+c}}
}
d=aaa(1)(2)(3)
console.log(d)

纯函数

  • 一类特别的函数:只要是同样的输入(实参),必定得到同样的输出(返回)
  • 必须遵守以下一些约束
    • 不得改写数据
    • 不会产生任何副作用,例如网络请求,输入和输出设备
    • 不能调用Date.now()或者Math.random()等不纯的方法

nanoid(现在这放着,懒得开新的了)

  • 安装 yarn add nanoid
  • 使用 import {nanoid} from ‘nanoid’;
  • 语法 nanoid()即可生成随机字符

instanceof

检查实例的原型链中,是否包含指定构造函数的原型

  function Person(name) {this.name = name}const p1 = new Person('小红');console.log(p1 instanceof Person) //trueconsole.log(p1 instanceof Object) //trueconsole.log(Person.prototype instanceof Object) //true

isPrototypeOf()

本质上,会在传入参数的[[prototype]]指向调用它的对象时返回true

  function Person(name) {this.name = name}const p1 = new Person('小红');const p2 = new Person('小明');console.log(Person.prototype.isPrototypeOf(p1)) //trueconsole.log(Person.prototype.isPrototypeOf(p2)) //true

Object.getPrototypeOf(obj)

可以方便的取得一个对象的原型。

  function Person(name) {this.name = name}const p1 = new Person('小红');console.log(Object.getPrototypeOf(p1)) //{constructor:f}console.log(Object.getPrototypeOf(p1)==Person.prototype) //true

Object.setPrototypeOf()

可以向实例的私有属性[[prototype]]写入一个新值,这样就可以重写一个对象的原型继承关系
【注意】这个方法可能会影响代码性能,会涉及所有访问了拿些修改过[[prototype]]的对象的代码

  Object.setPrototypeOf(p1, p2)// p1.__proto__===p2

Object.create()

来创建一个新对象,同时为其指定原型

  let biped = { numLegs: 2 };let person = Object.create(biped)person.name = 'Matt';console.log(person.name);  //'Matt'console.log(person.numLegs); //2console.log(Object.getPrototypeOf(person) === biped); //true

原型层级

  • 在通过对象访问属性时,会按照这个属性的名称开始搜索,搜索开始对象实例本身。
    如果在这个实例上发现了给定的名称,则返回该对象名称对应的值
  • 如果没有找到属性,则搜索会沿着指针进入原型对象,找到则返回该属性对应的值,
    这也就是原型用于在多个对象实例间共享属性的原理。

【注意】通过实例读取原型对象的值是不可更改的,如果在实例上添加一个与
原型对象同名的属性,则会在实例上创建这个属性,这样会遮住原型对象的属性

delect操作符

可以完全删除实例上的属性

  function Person(name) {this.name = name;}let p1 = new Person('小红');Person.prototype.name = '小明';console.log(p1.name) //'小红'delete p1.name;console.log(p1.name) //'小明'

hasOwnProperty()

检测是否为实例属性

  function Person() {}let p1 = new Person();let p2 = new Person();Person.prototype.name = '小明';p1.name = '小红';console.log(p1.hasOwnProperty('name'))  //trueconsole.log(p2.hasOwnProperty('name'))   //false

Object.getOwnPropertyDescriptor()

取得原型属性的描述符(只对实例属性有效)

  function Person() {}let p1 = new Person();let p2 = new Person();Person.prototype.name = '小明';p1.name = '小红';console.log(Object.getOwnPropertyDescriptor(p1, 'name'))  //{value: "小红", writable: true, enumerable: true, configurable: true}console.log(Object.getOwnPropertyDescriptor(p2, 'name'))   //undefined

in操作符

  function Person(name) {}let p1 = new Person();console.log('name' in p1)  //falsep1.name = '小明'console.log('name' in p1)  //truelet p2 = new Person();console.log('name' in p2)  //falsePerson.prototype.name = '小红'console.log('name' in p2)  //true//结论,无论属性在实例自身还是原型上都会返回true

利用in和hasOwnProperty的特性实现检测属性是否存在于原型上

  function detectionP(obj, k) {return !obj.hasOwnProperty(k) && ([k] in obj)}console.log(detectionP(p2, 'name'))

for-in循环中使用in操作符时,可以通过对象访问且可以被枚举的属性都会返回,
包括实例属性和原型属性

  function Person(name) {this.name = name}Person.prototype.age = 10let p1 = new Person('小红');Object.defineProperties(p1, {"school": {value: 'bgs',enumerable: true //默认false},"class": {value: '1908'}})console.log(p1) //Person {name: "小红", school: "bgs", class: "1908"}for (let k in p1) {console.log(k)  // name,school,age}

Object.keys()

接收一个对象作为参数,返回包含该对象所有可枚举属性名称的字符串数组

  function Person(name) {this.name = name}let p1 = new Person('小红');Object.defineProperties(p1, {"school": {value: 'bgs',enumerable: true //默认false},"class": {value: '1908'}})console.log(Object.keys(p1))  //['name']

Object.getOwnPropertyNames()

只要是实例属性(包含原型),无论是否可以枚举,返回对象所有属性名称的字符串数组

  function Person(name) {this.name = name}let k1 = Symbol('k1')let p1 = new Person('小红');Object.defineProperties(p1, {"school": {value: 'bgs',enumerable: true //默认false},"class": {value: '1908'},[k1]: {value: 1}})console.log(Object.getOwnPropertyNames(p1))  //["name", "school", "class"]

Object.getOwnPropertySymbols()

只针对符号,类似getOwnPropertyNames
语法Object.getOwnPropertySymbols(obj)

属性枚举的顺序

  • for-in和Object.keys()的枚举顺序是不确定的,取决于javascript引擎,
    可能因浏览器而异
  • Object.getOwnPropertyName()、Object.getOwnPropertySymbols()
    和object.assign()的枚举顺序是确定性的。
  • 先以升序枚举数值键,然后以插入顺序枚举字符串和符号键,
    在对象字面量中定义的键以它们逗号分隔的顺序插入。

ECMAScript2017新增两个静态方法

Object.values()

接收一个对象,返回对象值的数组(浅复制)

Object.entries()

接收一个对象,返回键值对数组(浅复制)。非字符串属性会被转换为字符串输出,
符号属性会被忽略

  let k1 = Symbol('k1')let o = {a: 1,b: 2,c() { },[k1]: 3}console.log(Object.values(o))  //[1,2,fn]console.log(Object.entries(o))  //[['a',1],['b',2],['c',fn]]

原型的语法

之前每次给原型上增加属性都要通过Person.prototype.key=value

function Person() { }//错误的写法1,会丢失constructor属性Person.prototype = {name: '小红',age: 10}const p1 = new Person()console.log(Person.prototype.constructor)  //ƒ Object() { [native code] }//错误的写法2,这样会得到一个[[Enumberable]]为true的constructor属性Person.prototype = {constructor: Person,name: '小红',age: 10}const p1 = new Person()console.log(p1.constructor) for (let k in p1) {console.log(k)   //name,age,constructor}//正确的写法Person.prototype = {name: '小红',age: 10}Object.defineProperty(Person.prototype, 'constructor', {value: Person,enumerable: false})const p1 = new Person()for (let k in p1) {console.log(k)   //name,age}

实例只有指向原型的指针,没有指向构造函数的指针.
重写构造函数上的原型之后在创建的实例才会引用引得原型。而再次之前创建的实例仍然会引用最初的原型

  //例1let p1 = new Num()function Num() {}Num.prototype.count = 2console.log(p1.count)  //2//例2let p1 = new Num()function Num() {}Num.prototype = {constructor: Num,count: 2}let p2 = new Num()console.log(p1.count)  //undefinedconsole.log(p2.count)  //2

toString()

方法可把一个 Number 对象转换为一个字符串,并返回结果。
一个参数:可以返回2~32进制的字符串

检查数据类型

Object.prototype.toString.call()

继承

原型链继承的问题

  • 主要问题出现在原型中包含引用值的时候(相同引用)
  • 子类型在实例化时不能给父类型的构造函数传参

盗用构造函数(也叫“经典继承”或“对象伪装”)

使用apply()和call()方法以新创建的对象为上下文执行构造函数
缺点不能访问父类原型上定义的方法

    function Animal(color) {this.color = color}function Dog(red, name) {Animal.call(this, red)this.name = name}const d1 = new Dog('红色', '小黄')console.log(d1)

组合继承

就是综合了原型链和盗用构造函数,将两者的优点结合。
基本思路就是使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性
调用过程中会执行两次SuperType函数

    function SuperType(name) {this.name = name;this.colors = ['red', 'blue', 'green'];}SuperType.prototype.sayName = function () {console.log(this.name);}function SubType(name, age) {// 继承属性SuperType.call(this, name);this.age = age;}// 继承方法SubType.prototype = new SuperType()SubType.prototype.sayAge = function () {console.log(this.age);}const instance1 = new SubType('小红', 19)instance1.sayAge()instance1.sayName()console.log(instance1)

寄生式组合继承(效果最佳) (红宝石248页)

只会调用一次SuperType函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/511036.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何快速构建服务发现的高可用能力

简介&#xff1a;保障云上业务的永远在线&#xff0c;是 MSE 一直在追求的目标&#xff0c;本文通过面向失败设计的服务发现高可用能力的分享&#xff0c;以及 MSE 的服务治理能力快速构建起服务发现高可用能力的演示&#xff0c;模拟了线上不可预期的服务发现相关异常发生时的…

火山引擎发布新一代数智平台VeDI,以数据驱动企业数字化增长

数据是“新石油”&#xff0c;经过提炼加工才能创造价值。 9月2日&#xff0c;火山引擎数据智能科技峰会在杭州举办。会上&#xff0c;火山引擎发布新一代企业级数据产品——数智平台VeDI&#xff08;Volcengine Data Intelligence&#xff09;&#xff0c;包括数据引擎、数据…

阿里云服务网格 ASM 正式发布商业化版本

简介&#xff1a;为了更好地满足企业日益加深的大规模使用服务网格产品、服务多语言互通、服务精细治理等需求&#xff0c;2022 年 4 月 1 日起&#xff0c;阿里云服务网格产品 ASM 正式发布商业化版本&#xff0c;为企业在生产环境下大规模落地服务网格能力提供性能、安全、高…

组件通信之pubsub

pubsub 释&#xff1a;消息订阅与发布 点击进入gitee 消息订阅与发布机制 1,先订阅,在发布 2,使用于任意组件间通信 3,要在组件的componentWillUnmount中取消订阅 作用 使用于任意组件间通信 安装 yarn add pubsub-js 引入(每个组件使用时都需要) 使用es6引入&#xff1a…

Redis消息队列发展历程

简介&#xff1a;Redis是目前最受欢迎的kv类数据库&#xff0c;当然它的功能越来越多&#xff0c;早已不限定在kv场景&#xff0c;消息队列就是Redis中一个重要的功能。Redis从2010年发布1.0版本就具备一个消息队列的雏形&#xff0c;随着10多年的迭代&#xff0c;其消息队列的…

手机+卫星,到底有多难?

作者 | 小枣君来源 | 鲜枣课堂这几天&#xff0c;关于卫星手机的新闻又火了。根据媒体报道&#xff0c;9月6日即将发布的华为Mate 50系列手机&#xff0c;将具备“卫星通信能力”&#xff0c;在没有网络的地方&#xff0c;可通过卫星系统发送紧急短信。无独有偶&#xff0c;另有…

一线技术人的成长思考总结

简介&#xff1a; 作为长期奋战在一线的技术人&#xff0c;我深刻体会到几个思维能力对技术人成长的重要性&#xff0c;熟练运用这几种思维可以帮助我们快速的进入到新的领域&#xff0c;在分析、定位和解决问题上有很大帮助。作为长期奋战在一线的技术人&#xff0c;我深刻体会…

算法篇(暂时就接触一个)

diff算法 逐层对比&#xff0c;最小的力度是标签 1、虚拟DOM中key的作用&#xff1a; 1-1、简单的说&#xff1a;key是虚拟DOM对象的标识&#xff0c;在更新显示时key起着极其重要的作用。2-2、详细的说&#xff1a;当状态的数据发生变化时&#xff0c;react会根据【新数据】…

sealer背后实现整个集群一键交付的奥秘 | 龙蜥技术

简介&#xff1a;解读集群镜像“开箱即用”神器——sealer&#xff01; 编者按&#xff1a;集群镜像把整个集群看成一台服务器&#xff0c;把 k8s 看成云操作系统&#xff0c;实现整个集群的镜像化打包和交付&#xff0c;为企业级软件提供一种“开箱即用”的应用封装技术。本文…

突发!GitHub 将关闭 Trending 热榜,开发者不答应

作者 | 苏宓出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;今天&#xff0c;当登录到 GitHub 上时&#xff0c;GitHub Trending 页面突然显示了这样一则通知&#xff1a;Heads up! This Trending tab is being deprecated. Due to low usage of Trending Reposito…

如何设计一条稳定的应用交付流程?|云效工程师指北

简介&#xff1a;如何设计一条稳定的应用交付流程&#xff1f;为持续交付的过程提供了规范化的可能&#xff0c;也引入了让人不时埋首于配置文件的小山里的麻烦。我们不妨从一次略有波折、稍显隐患的集成部署案例开始&#xff0c;看看如何着手设计一条更为稳定的应用交付流程。…

阿里云混合云开放网络生态的探索与实践

简介&#xff1a;2022年F5多云应用服务科技峰会于4月正式召开。阿里云智能混合云平台高级网络架构师张然&#xff08;然犀&#xff09;应邀于合作伙伴生态专场分享了阿里云混合云在开放网络生态领域的探索与实践。 2022年F5多云应用服务科技峰会于4月正式召开。阿里云智能混合…

阿里云启动超级智算中心,总算力达12 EFLOPS

8月30日&#xff0c;阿里云宣布正式启动张北超级智算中心&#xff0c;总建设规模为12 EFLOPS&#xff08;每秒1200亿亿次浮点运算&#xff09;AI算力&#xff0c;将超过谷歌的9 EFLOPS和特斯拉的1.8 EFLOPS&#xff0c;成为全球最大的智算中心&#xff0c;可为AI大模型训练、自…

领域驱动编程,代码怎么写?

简介&#xff1a;领域驱动开发最重要的当然是正确地进行领域拆解&#xff0c;这个拆解工作可以在理论的指导下&#xff0c;结合设计者对业务的深入分析和充分理解进行。本文假定开发前已经进行了领域划分&#xff0c;侧重于研究编码阶段具体如何实践才能体现领域驱动的优势。 …

8年持续增长,全闪存厂商PureStorage分享存储智能化的三大重要指标

作者 | 宋慧 出品 | CSDN云计算 从PureStorage去年宣布为现代数据应用提供多云环境提供存储即服务&#xff0c;已经过去了快一年时间。全闪存技术厂商PureStorage最近再次接受CSDN采访&#xff0c;分享这一年的发展和对全闪存市场的分析。 首先&#xff0c;今年PureStorage继…

插件类……

生成线上环境 安装&#xff1a; yarn add serve -g 使用&#xff1a;serve build 生成唯一id值 安装&#xff1a;yarn add nanoid 引入&#xff1a;import {nanoid} from nanoid 使用&#xff1a;nanoid()

深度解密|基于 eBPF 的 Kubernetes 问题排查全景图发布

简介&#xff1a;通过 eBPF 无侵入地采集多语言、多网络协议的黄金指标/网络指标/Trace&#xff0c;通过关联 Kubernetes 对象、应用、云服务等各种上下文&#xff0c;同时在需要进一步下钻的时候提供专业化的监测工具&#xff08;如火焰图&#xff09;&#xff0c;实现了 Kube…

西门子低代码本土化发展策略:社交化、个性化、智能化

作者 | 宋慧 出品 | CSDN 云计算 距离西门子低代码进入中国市场&#xff0c;已经过去了快两年时间。低代码从被技术开发者热烈和两极化的讨论&#xff0c;已经落地成为了企业数字化中的一个选项和方案。西门子低代码刚进入中国时&#xff0c;CSDN就曾做过报道&#xff0c;《Me…

技术抉择:阿里云13年后重构全部核心调度系统

简介&#xff1a;在阿里云十三年的发展历史上&#xff0c;重新设计调度系统算得上是一个重要的技术抉择。 在阿里云十三年的发展历史上&#xff0c;重新设计调度系统算得上是一个重要的技术抉择。 云计算是一个庞大的技术工程。2009 年&#xff0c;阿里云从 0 到 1 自建国产云…

hooks的常用Api

Ref Hook Ref Hook可以在函数组件中存储/查找组件内的标签或其他数据语法&#xff1a;const refContainer useRef()获取值 refContainer .current.value作用&#xff1a;保存标签对象&#xff0c;功能与React.creatRef()一样 Effect Hook 1、Effect Hook 可以让你在函数组件…