关于 typeof 与 instanceof 区别引出的原型对象问题

news/2024/4/21 13:50:15/文章来源:https://blog.csdn.net/A_9888/article/details/136534224

一、关于 typeof 与 instanceof 区别:

typeof 和 instanceof 是 JavaScript 中用于检查变量类型的两个不同操作符,它们在使用上有着明显的区别和不同的适用场景。

typeof

typeof 是一个一元操作符,用于返回一个变量或表达式的数据类型的字符串表示。它对于原始数据类型(如字符串、数字和布尔值)特别有用,但对于识别具体的对象类型(如区分数组和对象)则不那么有效。

语法:typeof operand

返回值:返回值为以下几种字符串之一:“undefined”、“object”、“boolean”、“number”、“string”、“function” 和 “symbol”。

特点:

对于原始类型,typeof 能够准确返回其类型。
对于所有对象(除了函数,函数会返回 “function”)和数组,typeof 都返回 “object”,这限制了它在区分数组、普通对象以及其他类型的对象(如日期和正则表达式)时的能力。
typeof null 返回 “object”,这是一个历史遗留的问题,需要特别注意。

instanceof

instanceof 是一个二元操作符,用于检查一个对象是否为一个特定构造函数的实例,或者说对象的原型链上是否存在构造函数的 prototype 属性(更准确地说,它检查右侧构造函数的 prototype 属性是否存在于左侧对象的原型链上。)。

语法:object instanceof constructor

返回值:如果对象是指定构造函数的实例,则返回 true;否则,返回 false。

特点:

instanceof 能够检查一个对象的原型链,因此它适用于判断对象的具体类型。
不能用于原始数据类型
。例如,一个字符串字面值不是 String 构造函数的实例,但如果你用 new String() 创建一个字符串对象,则 instanceof String 会返回 true。
它只适用于对象类型,不适用于原始数据类型。

二、instanceof 关于原型对象原型链的延伸知识

栗子
let c = '重庆'
c instanceof String //falselet d = new String('重庆') 
d instanceof String // trueconsole.log(c.__proto__) // String {'', anchor: ƒ, at: ƒ, big: ƒ, blink: ƒ, …
console.log(d.__proto__) // String {'', anchor: ƒ, at: ƒ, big: ƒ, blink: ƒ, …
//等价于 c.__proto__ === d.__proto__ //true
console.log(String.prototype) //String {'', anchor: ƒ, at: ƒ, big: ƒ, blink: ƒ, …}
由上面的例子产生疑问,为什么 c instanceof String 与 d instanceof String 输入不一样???

先来看看 MDN 对 js原型对象与原型链的解释

原型(Prototype)

在 JavaScript 中,原型是一个使对象能够继承属性和方法的特殊对象。每个 JavaScript 对象在创建时都会与另一个对象关联起来,这个对象就是它的原型,每个对象都从原型“继承”属性和方法。

JavaScript 使用构造函数来创建对象。每个构造函数都有一个 prototype 属性,这个属性是一个对象,包含应该被构造函数的实例继承的属性和方法。当你创建一个对象实例时,新对象内部的 [[Prototype]](或者通过 proto 属性暴露出的原型链)指向构造函数的 prototype 对象。

function Person(name) {this.name = name;
}
Person.prototype.sayHello = function() {console.log(`Hello, my name is ${this.name}`);
};const person1 = new Person("John");
person1.sayHello(); // 输出: Hello, my name is John
console.log(person1.__proto__ === Person.prototype); // 输出: true

在上面的例子中,person1 对象的原型是 Person.prototype,因此 person1 可以访问 sayHello 方法。

原型链(Prototype Chain)

原型链是 JavaScript 实现继承和查找对象属性的机制。当试图访问一个对象的属性时,如果对象本身没有这个属性,解释器就会去对象的原型(proto 属性指向的对象)中查找。如果原型对象也没有这个属性,解释器再去原型的原型中查找,如此递归下去,形成了所谓的“原型链”。

如果一直查找到原型链的顶端(Object.prototype),仍然没有找到指定的属性,就会返回 undefined。这个查找过程就是 JavaScript 中的原型继承机制。

function Animal(name) {this.name = name;
}
Animal.prototype.eat = function() {console.log(`${this.name} eats.`);
};function Dog(name) {Animal.call(this, name);
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;Dog.prototype.bark = function() {console.log('Woof!');
};const dog1 = new Dog("Rex");
dog1.eat(); // 输出: Rex eats.
dog1.bark(); // 输出: Woof!

在这个例子中,Dog 的实例 dog1 既可以访问 Dog.prototype 上定义的 bark 方法,也可以访问 Animal.prototype 上定义的 eat 方法,因为 Dog.prototype 的原型是 Animal.prototype,这就形成了一个原型链。

总结

原型是一个对象,其他对象可以通过它实现属性和方法的继承。
原型链是一种机制,它提供了属性查找的路径,使得对象可以访问原型中定义的属性和方法。原型链的末端是 Object.prototype,所有的JavaScript对象都直接或间接地继承自 Object.prototype。
即:构造函数的.prototype(显示原型) 指向了(===)实例对象的.proto (隐式原型)

为什么 c instanceof String 与 d instanceof String 输入不一样???

在这里插入图片描述

① 结合上面instanceof 的含义内容,(它检查右侧构造函数的 prototype 属性是否存在于左侧对象的原型链上);由于 c 是通过字面量创建的是一个原始字符串。原始字符串不是一个对象,它仅仅只是 JavaScript 中的一种原始数据类型;
② String 对象:当d使用 new String(‘重庆’) 时,创建的是一个 String 对象。这个对象包装了字符串值,使得您能够在它上面调用各种字符串方法,但它是通过 String 构造函数生成的一个对象实例。
③ instanceof 操作符 检查的是一个对象的原型链上是否存在一个构造函数的 prototype 属性。因此,c instanceof String 返回 false,因为 c 是一个原始字符串,而不是一个对象。原始类型(如字符串字面量、数字、布尔值)不是通过构造函数创建的,因此它们的 instanceof String 检查会返回 false。
④相反,c instanceof String 返回 true,因为 d 是通过 String 构造函数创建的对象,它的原型链上确实存在 String.prototype。
⑤__proto__ 属性 是对象特有的属性,它指向该对象的原型。对于通过 new String(‘重庆’) 创建的 String 对象,d.proto 实际上指向了 String.prototype,这是所有 String 对象共享的原型。

虽然原始字符串不是对象,但当您尝试访问原始字符串的属性或方法时(比如调用字符串的 .length 属性或 .toUpperCase() 方法),JavaScript 引擎会临时将原始字符串通过内置的 String 对象包装起来,以便可以访问 String.prototype 上定义的方法。这是一个自动的、内部的包装过程,但并不改变原始字符串不是对象的事实。

因此,c instanceof String 和 d instanceof String 的不同结果,准确地反映了原始字符串和 String 对象之间的区别,以及 JavaScript 如何处理这两种不同类型的字符串的细节。

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

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

相关文章

常见BUG如何在测试过程中分析定位

前言 在测试的日常工作中,相信经常有测试的小伙伴遇到类似的情况:在项目上线时,只要出现问题(bug),就很容易成为“背锅侠”。 软件测试人员在工作中是无法避免的要和开发人员和产品经理打交道的&#xff…

每日一题——LeetCode2575.找出字符串的可整除数组

方法一 暴力(不可行) 直接循序字符串,每次多取一位,转为整数型然后去除m,但是后面word的长度会很长,转为整数时会丢失精度,得到的结果不准确,如果使用大数字型BigInt()也不行&#…

开发一套小程序所需的费用取决于多个因素

随着移动互联网的发展,小程序已经成为许多企业和个人推广业务和服务的重要工具。 不过,对于很多想要开发小程序的人来说,最大的疑问就是开发一套小程序要花多少钱。 这个问题的答案并不是固定的,因为开发一个小程序的成本取决于几…

Kubernetes(K8S第三部分之资源控制器)

资源控制器 什么是控制器 Kubernetes中内建了很多controller(控制器),这些相当于一个状态机,用来控制Pod的具体状态和行为。 控制器类型 ReplicationController和ReplicaSet Deployment DaemonSet StateFulSet Job/CronJob…

【ArcPy】游标访问几何数据

访问质心坐标相关数据 结果展示 代码 import arcpy shppath r"C:\Users\admin\Desktop\excelfile\a2.shp" with arcpy.da.SearchCursor(shppath, ["SHAPE","SHAPEXY","SHAPETRUECENTROID","SHAPEX","SHAPEY",&q…

前端canvas项目实战——简历制作网站(五):右侧属性栏(字体、字号、行间距)

目录 前言一、效果展示二、实现步骤1. 优化代码,提取常量2. 实现3个编辑模块3. 实现updateFontProperty方法4. 一个常见的用法:仅更新当前选中文字的样式 三、Show u the code后记 前言 上一篇博文中,我们扩充了线条对象(fabric.…

MongoDB Java实战

📕作者简介: 过去日记,致力于Java、GoLang,Rust等多种编程语言,热爱技术,喜欢游戏的博主。 📗本文收录于MongoDB系列,大家有兴趣的可以看一看 📘相关专栏Rust初阶教程、go语言基础…

蓝色经典免费wordpress模板主题

蓝色经典配色的免费wordpress建站主题,万能的wordpress建站主题。 https://www.wpniu.com/themes/24.html

S4---FPGA-K7板级原理图硬件实战

视频链接 FPGA-K7板级系统硬件实战01_哔哩哔哩_bilibili FPGA-K7板级原理图硬件实战 基于XC7K325TFFG900的FPGA硬件实战框图 基于XILINX 的KINTEX-7 芯片XC7K325FPGA的硬件平台,FPGA 开发板挂载了4 片512MB 的高速DDR3 SDRAM 芯片,另外板上带有一个SODIM…

kafka查看消息两种方式(命令行和软件)+另附发送消息方式

1、命令行方式 ①找到kafka安装文件夹 ②执行命令 #指定offset为指定时间作为消息起始位置 kafka-consumer-groups.sh \ --bootstrap-server 20.2.246.116:9092 \ --group group_1 \ --topic lanxin_qiao \ --reset-offsets \ --to-datetime 2023-07-19T01:00:00.000 \ -exe…

软件测试工程师必备的27个基础技能

混迹于软件测试这么长时间了,一直想写一篇关于软件测试的经验分享的文章,但苦于工作原因迟迟未下笔。最近终于有了些闲余时间,遂决定把自己的心路历程及所感所想记录下来,与各位同行共勉。 以我多年的工作经验来看,软…

图文并茂的讲清楚Linux零拷贝技术

今天我们来聊一聊Linux零拷贝技术,今天我们以一个比较有代表性的技术sendfile系统调用为切入点,详细介绍一下零拷贝技术的原理。 1.零拷贝技术简介 Linux零拷贝技术是一种优化数据传输的技术,它可以减少数据在内核态和用户态之间的拷贝次数&…

乐得瑞 1C to 2C快充线:引领充电数据线新潮流,高效快充解决接口难题

随着科技的不断进步,数据线的接口种类也日渐繁多,但在早些时候,三合一和二合一的数据线因其独特的设计而备受欢迎。这类数据线通常采用USB-A口作为输入端,并集成了Micro USB、Lightning以及USB-C三种接口,满足了当时市…

JeecgBoot Vue3前端项目性能优化按需加载方案

JeecgBoot vue3前端项目在 3.5.5 版本之前,的确存在很严重的性能问题,大家可以参考以下文档进行升级。 按需加载改造方法 1、全局注册地方去掉2、组件改成异步注册3、用不到的大组件可以删掉 【精简项目方案】 大组件 1、富文本 tinyme2、Markdown3、…

数据库压力测试方法概述

一、前言 在前面的压力测试过程中,主要关注的是对接口以及服务器硬件性能进行压力测试,评估请求接口和硬件性能对服务的影响。但是对于多数Web应用来说,整个系统的瓶颈在于数据库。 原因很简单:Web应用中的其他因素,…

C++ · 代码笔记5 · 探索多态与虚函数

目录 前言011虚函数_使用基类指针实现覆盖特性012虚函数_使用引用实现覆盖特性013使用多态场景小例程020构成多态的条件030虚析构函数040纯虚函数051typeinfo运算符_获取类型信息052typeinfo_根据不同类型进行不同操作 前言 本笔记所涉及到的编程环境与 《C 代码笔记1 从C到C…

9道软件测试面试题,刷掉90%的测试程序员

没点真本事真技术,没点面试经验,不了解点职场套路,如何过五关斩六将?如何打败面试官?如何拿下那梦寐以求的offer? 如果你的跳槽意向已经很确定,那么请往下看! 跳槽最重要的一步自然…

完美解决VMware中配置suse10虚拟机网络

一、注意!!!配置suse10网络,需要在虚拟机关机状态下进行,否则会配置不成功; 二、配置与主机在同一网段(仅主机模式,网卡一); 在suse系统关机状态下,Vmware中设置”虚拟网…

UE5 文字游戏(2) C++实时读取CSV文件(游戏开始读取本地CSV剧本)

1.结构体代码 // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "Engine/DataTable.h" #include "MyCharacterStats.generated.h"USTRUCT(BlueprintType) struc…

记录 android studio 通过安装NDK 编译C文件,得到需要的so文件

只怪自己太健忘,每次网上查了一圈,搞定后,再遇到又发现不会操作了,特此记下 不废话直接上步骤 (1) 进入AS的settinging如下界面 (2)选中图片箭头两个文件 进行下载 (…