【ES新特性三】Object 原型、原型链相关方法

一、Object 原型、原型链相关方法

1.1 静态方法(Object 调用):

  • Object.setPrototypeOf(obj,prototype) 方法用于设置某个实例对象的原型(可以是null,也可以是一个对象)

  • Object.getPrototypeOf(obj)

​ 注:ES5之前,实例化对象通过 __proto__ 属性来获取原型对象;ES5中,不推荐以 __ 开头的语句,所以提供了 getPropertyOf() 方法用于获取对象的原型对象

原生JavaScipt案例合集
JavaScript +DOM基础
JavaScript 基础到高级
Canvas游戏开发

1.2 原型方法(实例调用)

此方法为 Object.prototype 原型方法,Object.prototype 作为任意对象在原型链上的顶级原型对象,在 JS 中定义的任意一个对象(自定义对象、数组对象等都可以调用子方法)。

  • isPrototypeOf() 方法用于测试一个对象是否存在于另一个对象的原型链上。
  • hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。
<body>
<ul><li>111</li><li>222</li><li>333</li><li>444</li>
</ul>
</body>
<script>// 获取类数组对象var lis = document.getElementsByTagName("li");// 定义数组var arr = [10,20,30,40];// 自定义对象var obj = {name:"张三"}// 查看Array.prototype这个原型是哪个实例化对象的原型console.log(Array.prototype.isPrototypeOf(lis));//falseconsole.log(Array.prototype.isPrototypeOf(obj));//falseconsole.log(Array.prototype.isPrototypeOf(arr));//true// 查找过程中,会查找整个原型链console.log(Object.prototype.isPrototypeOf(lis));//trueconsole.log(Object.prototype.isPrototypeOf(obj));//trueconsole.log(Object.prototype.isPrototypeOf(arr));//true// 获取实例化对象 arr 的原型对象// 原始方式console.log(arr.__proto__);//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]// ES5方式console.log(Object.getPrototypeOf(arr));//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]// 对比console.log(arr.__proto__ === Object.getPrototypeOf(arr));//true// 设置实例化对象 arr 的原型对象  可以为null 也可以是一个对象  会修改整个原型链Object.setPrototypeOf(arr,null);console.log(Object.getPrototypeOf(arr));//nullObject.setPrototypeOf(arr,{a:10});console.log(Object.getPrototypeOf(arr));//{a:10}// 构造函数的原型不变  只是实例化对象原型指向改变console.log(Array.prototype);//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
</script>
  • __proto__ 属性是一个访问器属性(一个 getter 函数和一个 setter 函数), 暴露了通过它访问的对象的内部[[Prototype]] (一个对象或 null)。proto 属性也可以在对象文字定义中使用对象 [[Prototype]] 来创建,作为Object.create() 的一个替代。

1.3 操作属性的方法(Object 调用)

**Object.getOwnPropertyNames()**方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性)组成的数组。

Object.getOwnPropertySymbols() 方法返回一个给定对象自身的所有 Symbol 属性的数组。

Object.hasOwn() 如果指定的对象自身有指定的属性,则返回 true。如果属性是继承的或者不存在,该方法返回 false

备注: Object.hasOwn() 旨在取代 Object.hasOwnProperty()

// 类数组对象
var obj = { 0: "a", 1: "b", 2: "c"};
console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]// 数组对象
var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]// Symbols 
var obj = {};
var a = Symbol("a");
var b = Symbol.for("b");
obj[a] = "localSymbol";
obj[b] = "globalSymbol";
var objectSymbols = Object.getOwnPropertySymbols(obj);// hasOwn()
const example = {};
Object.hasOwn(example, 'prop');   // false - 'prop' has not been definedexample.prop = 'exists';
Object.hasOwn(example, 'prop');   // true - 'prop' has been defined

二、Object 相关方法

2.1 Object.preventExtensions() 取消对象可拓展性

Object.preventExtensions(obj) 方法用于取消对象的可拓展性

Object.isExtensible(obj) 判断对象是否取消了可拓展性。返回值是一个布尔值,返回true对象可以拓展属性 返回false对象不可拓展属性

注:当一个对象被取消了可拓展性之后,对象不能再拓展属性,但是可以修改和删除属性

var obj = {a:1,b:2
}console.log("取消对象可拓展性前对象:",obj);// 取消对象拓展
Object.preventExtensions(obj);// 拓展属性
obj.c = 3;// 删除属性
delete obj.a;// 修改属性值
obj.b = 22;// 判断对象是否可拓展
console.log(Object.isExtensible(obj));//trueconsole.log("取消对象可拓展性后并操作属性后的对象:",obj);

2.2 Object.seal() 封闭对象

Object.seal(obj) 封闭对象的属性

Object.isSealed(obj) 判断对象属性是否被封闭。返回值布尔值,返回true 对象被封闭 返回false对象没有被封闭

注:当一个对象被封闭后,不能拓展和删除属性,但是可以修改属性。

var obj = {a:1,b:2
}console.log("封闭前对象:",obj);// 封闭对象
Object.seal(obj);// 拓展属性
obj.c = 3;// 删除属性
delete obj.a;// 修改属性值
obj.b = 22;// 判断对象是否被封闭
console.log(Object.isSealed(obj));//trueconsole.log("封闭后并操作属性后的对象:",obj);

2.3 Object.freeze() 冻结对象

Object.freeze(obj) 方法用于冻结对象的属性

Object.isFrozen(obj) 方法用于判断对象属性是否被冻结。返回值 一个布尔值 返回true对象被冻结,返回false对象没有被冻结

注:当一个对象被冻结后,不能拓展、修改和删除对象的属性

var obj = {a:1,b:2
}console.log("冻结前对象:",obj);// 冻结对象
Object.freeze(obj);// 拓展属性
obj.c = 3;// 删除属性
delete obj.a;// 修改属性值
obj.b = 22;// 判断对象是否被冻结
console.log(Object.isFrozen(obj));//trueconsole.log("冻结后并操作属性后的对象:",obj);

2.4 Object.create() 创建对象

Object.create(proto,[ propertiesObject ]) 方法使用现有对象作为新创建的对象的原型来创建新对象。

  • 参数

    • proto 该对象应该是新创建对象的原型。可以是null
    • propertiesObject 可选的。指定要添加到新创建的对象的属性描述符,以及相应的属性名称。这些属性对应于的第二个参数Object.defineProperties()对象属性的特性。
  • 返回值 具有指定原型对象和属性的新对象。

// 学过的创建对象的方式
// var obj = {};
// var obj1 = new Object();
// var obj2 = Object();// ES5新增创建一个空对象  第一个参数新创建对象的原型设置为null
// var obj3 = Object.create(null);
// console.log(obj3)//使用Object.create() 来创建一个对象,第一个参数原型对象为一个常量对象
// var obj = Object.create({
//     sayHi:function(){
//         console.log("Hello");
//     }
// })// 第一个参数为空,第二个参数为 要创建对象的空对象的属性特性描述(类似于Object.defineProperty()设置的对象特性)
// var obj = Object.create(null,{
//     name:{
//         // 配置值
//         value:"张三",
//         // 配置是否可写
//         writable:false,
//         // 配置是否可枚举
//         enumerable:false
//     },
//     age:{
//         // 配置值
//         value:10,
//          // 配置是否可写
//          writable:false,
//     }
// })
// console.log(obj);
// console.log(obj.name);
// // 通过这种对象特性的方式创建的对象,默认属性不能被删除 修改
// obj.name = "haha";
// delete obj.age;
// console.log(obj);
// console.log(obj.name);// 创建一个对象,并能继承另外一个对象的方法;将一个对象作为另外一个对象的原型
// 创建需要的原型对象
var prototype = {sayHi:function(){console.log("Hello");}
}// 创建需要的特性属性对象
var options = {name:{// 配置值value:"张三",// 配置是否可写writable:false,// 配置是否可枚举enumerable:false},age:{// 配置值value:10,// 配置是否可写writable:false,}
}// 两者组合创建对象
var obj = Object.create(prototype,options);console.log(obj)//查看原型
obj.sayHi();

2.5 Object.create()完善继承

// 定义父类
function People(name,sex,age){this.name = name;this.sex = sex;this.age = age;
}// 原型中定义方法
People.prototype.sayHi = function(){return "姓名:" + this.name + ",性别:" + this.sex + ",年龄:" + this.age;
}People.prototype.sayHello = function(){return "Hello";
}// 定义子类
function Student(name,sex,age,score){// applay实现继承(改变调用对象People.apply(this,arguments);// 定义子类拓展的属性this.score = score;
}// var p = new People();
// delete p.name;
// delete p.sex;
// delete p.age;// 子类继承父类中的方法 必须要使用原型继承 将子类的原型指向父类的实例
// Student.prototype = new Student();// 使用Object.create()优化继承
Student.prototype = Object.create(People.prototype);// 原型继承会造成结构的紊乱,将原型对象的构造函数手动改回到Student
Student.prototype.constructor = Student;// 实例化对象
var s = new Student("张三","男",23,100);// 调用父类原型中的方法
console.log(s.sayHi());/*
* 原型继承,子类的原型就是父类的实例,这种方式会在子类的原型中多出几个无用的属性
* 此时,会在子类的原型中多出几个属性:name:undefined,age:undifined,sex:undefined
* 如果不考虑寄生组合继承这种方式进行优化,ES5还提供了Object.create()方法来优化
**/

2.6 封装实现Object.create()方法

// 定义父类
function People(name,sex,age){this.name = name;this.sex = sex;this.age = age;
}// 原型中定义方法
People.prototype.sayHi = function(){return "姓名:" + this.name + ",性别:" + this.sex + ",年龄:" + this.age;
}People.prototype.sayHello = function(){return "Hello";
}// 定义子类
function Student(name,sex,age,score){// applay实现继承(改变调用对象People.apply(this,arguments);// 定义子类拓展的属性this.score = score;
}// 取消Object.create方法
Object.create = null;
// 重新自定义 create 方法,实现相同的功能
Object.create = function(prototype){// 定义一个构造函数var F = function(){}// 将F的原型指向传入的原型F.prototype = prototype;// 返回F的实例return new F();
}// 使用Object.create方法实现继承
Student.prototype = Object.create(People.prototype);// 实例化对象
var s = new Student("张三","男",23,100);
console.log(s.sayHi());

2.7 Object.entries() 等返回可枚举数组方法

Object.entries() 方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。

Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致。

Object.values() 方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用 for...in 循环的顺序相同(区别在于 for-in 循环枚举原型链中的属性)。

const info = {name: "Jack",country: "Russia",age: 35
}// 使用 Object.keys() 将对象所有自身可枚举属性收集到一个新数组中
const keys = Object.keys(info);// 使用 Object.values() 将对象所有自身可枚举值收集到一个新数组中
const values = Object.values(info);// 使用 Object.entries() 将对象所有自身可枚举所有键值对收集到一个新数组中
const keyVals = Object.entries(info)
// 使用 for...of 遍历自身的键值对(key 和 value)
for (const [key, value] of keyVals) {console.log(`${key}: ${value}`);
}

2.8 Object.assign()

Object.assign(target, …sources) 方法将所有可枚举(Object.propertyIsEnumerable() 返回 true)的自有(Object.hasOwnProperty() 返回 true)属性从一个或多个源对象复制到目标对象,返回修改后的对象。如果目标对象与源对象具有相同的 key,则目标对象中的属性将被源对象中的属性覆盖

参数: target 目标对象,接收源对象属性的对象,也是修改后的返回值。

​ sources 源对象,包含将被合并的属性。

返回值:目标对象

注意点

  1. 针对 深拷贝, 需要使用其他办法,因为 Object.assign() 只复制属性值。假如源对象是一个对象的引用,它仅仅会复制其引用值(地址)。
  2. 原型链生的属性以及不可枚举属性不能被复制
'use strict';// Object.assign() 属于浅拷贝
let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);
console.log(JSON.stringify(obj2)); // { "a": 0, "b": { "c": 0}}obj1.a = 1;
console.log(JSON.stringify(obj1)); // { "a": 1, "b": { "c": 0}}
console.log(JSON.stringify(obj2)); // { "a": 0, "b": { "c": 0}}obj2.a = 2;
console.log(JSON.stringify(obj1)); // { "a": 1, "b": { "c": 0}}
console.log(JSON.stringify(obj2)); // { "a": 2, "b": { "c": 0}}obj2.b.c = 3;
console.log(JSON.stringify(obj1)); // { "a": 1, "b": { "c": 3}}
console.log(JSON.stringify(obj2)); // { "a": 2, "b": { "c": 3}}// 深拷贝(深度克隆)
obj1 = { a: 0 , b: { c: 0}};
let obj3 = JSON.parse(JSON.stringify(obj1));
obj1.a = 4;
obj1.b.c = 4;
console.log(JSON.stringify(obj3)); // { "a": 0, "b": { "c": 0}}// 合并对象
const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, target object itself is changed.//合并相同属性的对象
const o1 = { a: 1, b: 1, c: 1 };
const o2 = { b: 2, c: 2 };
const o3 = { c: 3 };const obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }

2.9 Object.is() 判断两个值是否为同一个值。

Object.is(value1, value2) 方法判断两个值是否为同一个值,如果满足以下任意条件则两个值相等:

  • 都是 undefined
  • 都是 null
  • 都是 true 或都是 false
  • 都是相同长度、相同字符、按相同顺序排列的字符串
  • 都是相同对象(意味着都是同一个对象的值引用)
  • 都是数字且
    • 都是 +0
    • 都是 -0
    • 都是 NaN
    • 都是同一个值,非零且都不是 NaN

Object.is()== 不同。== 运算符在判断相等前对两边的变量(如果它们不是同一类型)进行强制转换(这种行为将 "" == false 判断为 true),而 Object.is 不会强制转换两边的值。

Object.is()=== 也不相同。差别是它们对待有符号的零和 NaN 不同,例如,=== 运算符(也包括 == 运算符)将数字 -0+0 视为相等,而将 Number.NaNNaN 视为不相等。

// Case 1: Evaluation result is the same as using ===
Object.is(25, 25);                // true
Object.is('foo', 'foo');          // true
Object.is('foo', 'bar');          // false
Object.is(null, null);            // true
Object.is(undefined, undefined);  // true
Object.is(window, window);        // true
Object.is([], []);                // false
var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo);              // true
Object.is(foo, bar);              // false// Case 2: Signed zero
Object.is(0, -0);                 // false
Object.is(+0, -0);                // false
Object.is(-0, -0);                // true
Object.is(0n, -0n);               // true// Case 3: NaN
Object.is(NaN, 0/0);              // true
Object.is(NaN, Number.NaN)        // true

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

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

相关文章

Day5:react函数组件与类组件

「目标」: 持续输出&#xff01;每日分享关于web前端常见知识、面试题、性能优化、新技术等方面的内容。 「主要面向群体&#xff1a;」前端开发工程师&#xff08;初、中、高级&#xff09;、应届、转行、培训、自学等同学 Day4-今日话题 react「函数组件和类组件」的区别&…

MPI之数据打包和解包

MPI_Pack 和 MPI_Unpack 它们可以将源数据打包成二进制格式以便于传输&#xff0c;或者将二进制格式的数据解包成目标数据。这对函数通常用于在 MPI 应用程序中进行异构系统间的通信&#xff0c;即两个系统之间使用不同的二进制格式进行交互通信。 打包&#xff08;序列化&…

javaScipt

javaScipt 一、JavaScript简介二、javaScript基础1、输入输出语法2、变量3、常量4、数据类型4.1、数字型 number4.2、字符串类型 string4.3、布尔类型 boolean4.4、未定义类型 undefined4.5、null 空类型4.6、typeof 检测变量数据类型 5、数据类型转换5.1、隐式转换5.2、显示转…

容器技术Linux Namespaces和Cgroups

对操作系统了解多少&#xff0c;仅仅敲个命令吗 操作系统虚拟化&#xff08;容器技术&#xff09;的发展历程 1979 年&#xff0c;UNIX 的第 7 个版本引入了 Chroot 特性。Chroot 现在被认为是第一个操作系统虚拟化&#xff08;Operating system level virtualization&#x…

QT基础教程之七Qt消息机制和事件

QT基础教程之七Qt消息机制和事件 事件 事件&#xff08;event&#xff09;是由系统或者 Qt 本身在不同的时刻发出的。当用户按下鼠标、敲下键盘&#xff0c;或者是窗口需要重新绘制的时候&#xff0c;都会发出一个相应的事件。一些事件在对用户操作做出响应时发出&#xff0c…

【面经】字节测开实习岗面试题分享

1、自我介绍 2、为什么投了字节&#xff1f; 公司声誉&#xff1a;字节跳动是一家知名的科技公司&#xff0c;在互联网行业享有很高的声誉。 发展前景&#xff1a;字节跳动的业务涵盖了多个领域&#xff0c;包括短视频、资讯、教育等。这意味着您将有机会接触到不同的产品和…

C++通过JNI调用JAVA方法返回ArrayList对象

运行效果: JAVA实现: 获取系统已安装应用列表并返回List<String>对象 //使用系统API获取安装包列表public List<String> getAppList(MainActivity act) {List<String> packages = new ArrayList<String>();try {//取包信息列表List<PackageInf…

spring高级源码50讲-9-19(springAOP)

文章目录 AOP9) AOP 实现之 ajc 编译器收获&#x1f4a1; 10) AOP 实现之 agent 类加载收获&#x1f4a1; 11) AOP 实现之 proxy演示1 - jdk 动态代理收获&#x1f4a1;演示2 - cglib 代理收获&#x1f4a1; 12) jdk 动态代理进阶演示1 - 模拟 jdk 动态代理收获&#x1f4a1;演…

我的私人笔记(安装hive)

1.hive下载&#xff1a;Index of /dist/hive/hive-1.2.1 或者上传安装包至/opt/software&#xff1a;rz或winscp上传 2.解压 cd /opt/software tar -xzvf apache-hive-1.2.1-bin.tar.gz -C /opt/servers/ 3.重命名 mv apache-hive-1.2.1-bin hive 4.配置环境变量 vi /etc/…

计算机网络 概述部分

目录 计算机网络在信息时代的作用 计算机网络的重要特征 网络&#xff0c;internet,Internet的区别 局域网 广域网的区别 网络协议的分层 计算机网络在信息时代的作用 计算机网络的重要特征 连通性&#xff1a;彼此联通&#xff0c;交换信息 共享性&#xff1a;信息共享…

Java实现根据关键词搜索当当商品列表数据方法,当当API接口申请指南

要通过当当网的API获取商品列表数据&#xff0c;您可以使用当当开放平台提供的接口来实现。以下是一种使用Java编程语言实现的示例&#xff0c;展示如何通过当当开放平台API获取商品列表&#xff1a; 首先&#xff0c;确保您已注册成为当当开放平台的开发者&#xff0c;并创建…

老程序员教你如何笑对问题,轻松培养逻辑思考和解决问题的能力

原文链接 ​​​​​​​老程序员教你如何笑对问题&#xff0c;轻松培养逻辑思考和解决问题的能力 故事发生在一个阳光明媚的午后&#xff0c;我们的主人公&#xff0c;老李&#xff0c;一位拥有十年工作经验的 Python 老程序员&#xff0c;正悠哉地在喝着咖啡。 这时&#x…

Android 12 源码分析 —— 应用层 三(SystemUIFactory及其Dependency解析)

Android 12 源码分析 —— 应用层 三&#xff08;SystemUIFactory及其Dependency解析&#xff09; 在上一篇文章中&#xff0c;介绍了SystemUI的启动流程&#xff0c;并且简单提及了Dagger2用来管理各个SystemUI中要用的依赖。而这部分代码就在&#xff1a;mContextAvailableC…

Java动态代理

所有interface类型的变量总是通过某个实例向上转型并赋值给接口类型变量的&#xff1a; CharSequence cs new StringBuilder(); //父类(CharSequence) 指向 子类&#xff08;StringBuilder&#xff09;&#xff0c;且没有强转符号 > 向上转型。 有没有可能不编写实现类…

扫盲:常用NoSQL数据库

前言 关系型数据库产品很多&#xff0c;如 MySQL、Oracle、Microsoft SQL Sever 等&#xff0c;但它们的基本模型都是关系型数据模型。 非关系型数据库又称为&#xff1a;NoSQL &#xff0c;没有统一的模型&#xff0c;而且是非关系型的。 常见的 NoSQL 数据库包括键值数据库、…

构建前端之光:JavaScript插件的研发艺术

前言 在前端开发的宇宙中&#xff0c;星星是网页&#xff0c;而照亮这个宇宙的&#xff0c;是我们前端开发者手中的JavaScript插件。插件就像乐高积木&#xff0c;可以将我们的代码块组装成复杂而精美的页面。本文将引导你走进JavaScript插件的世界&#xff0c;探讨如何开发、…

python unitest自动化框架

以下举一个最简单的unitest实例&#xff0c;包含备注&#xff0c;自己拉取代码运行一次就知道原理了 import unittest import osclass TestSample(unittest.TestCase):classmethoddef setUpClass(cls) -> None:print(整个测试类只执行一次)def setUp(self) -> None:prin…

const {}解构赋值

定义&#xff1a;ES6允许按照一定模式&#xff0c;从数组和对象中提取值&#xff0c;对变量进行赋值&#xff0c;这被称为解构&#xff08;Destructuring&#xff09;。 解构赋值的基本规则&#xff1a;只要等号右边不是对象或数组&#xff0c;就先将其转换为对象。由于undefi…

Prometheus+grafana安装配置

Prometheus安装配置 Prometheus下载地址 官方地址&#xff1a;Download | Prometheus 可根据系统版本下载想要的安装包&#xff0c;复制链接地址 wget https://github.com/prometheus/prometheus/releases/download/v2.33.3/prometheus-2.33.3.linux-amd64.tar.gzwg 解压pr…

系列五、Java操作RocketMQ简单消息之同步消息

一、概述 同步消息的特征是消息发出后会有一个返回值&#xff0c;即RocketMQ服务器收到消息后的一个确认&#xff0c;这种方式非常安全&#xff0c;但是性能上却没有那么高&#xff0c;而且在集群模式下&#xff0c;也是要等到所有的从机都复制了消息以后才会返回&#xff0c;适…