js补环境系列之剖析:原型、原型对象、实例对象三者互相转化(不讲废话、全是干货)

news2024/12/28 3:10:58

【作者主页】:小鱼神1024

【擅长领域】:JS逆向、小程序逆向、AST还原、验证码突防、Python开发、浏览器插件开发、React前端开发、NestJS后端开发等等

思考下:js补环境中,什么场景会用到原型、原型对象、实例对象?

举例说明:

在js补环境中,大多数平台会用 navigator 中的 userAgent 作为 环境检测点。你是不是可能会这样补:

var window = {};
var navigator = {
    userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36"
}
window.navigator = navigator

如果平台检测的是 window.navigator.userAgent 或者 navigator.userAgent,那么这样补环境是没问题的。

但是,如果平台通过 Object.getOwnPropertyDescriptor(window.navigator, "userAgent") 获取对象属性描述符,那么这样补环境就出问题了。

js补环境系列-原型、原型对象、实例对象

可以发现,在浏览器控制台中打印输出为:undefined

js补环境系列-原型、原型对象、实例对象

可以发现,在 Node 环境下打印输出为:

{
  value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36',
  writable: true,
  enumerable: true,
  configurable: true
}

很明显,浏览器和 Node 环境下得到的结果是不一样的。所以得到的加密结果也是不一样的。

那么,如何解决这个问题呢?

相信阅读完这篇文章后,你会有答案的。

为了方便理解,本文不会讲解太多基础概念,让人看的云里雾里的。我直接举例说明:

原型

定义一个用户 原型,它其实就是一个函数,首写字母大写。

function User() {

}
console.log("原型", User)

// 输出结果:[Function: User]

原型对象

可以通过 prototype 获取 原型原型对象

首先,我们来看下 User 函数的 原型对象 是什么。

console.log("原型对象", User.prototype)

// 输出结果:{ }

得到的是一个空对象,那是因为还没定义任何 属性方法

通过给 User.prototype 定义 属性方法后,再次打印:

function User() {

}
User.prototype = {
    username: "小鱼神1024",
    password: "12345678",
    login() {
        return `用户名:${this.username}\r\n密码:${this.password}`;
    }
}
console.log("原型对象", User.prototype)

// 输出结果:{ username: '小鱼神1024', password: '12345678', login: [Getter] }

实例对象

实例对象是通过 new 关键字创建的。

function User() {

}
User.prototype = {
    username: "小鱼神1024",
    password: "12345678",
    login() {
        return `用户名:${this.username}\r\n密码:${this.password}`;
    }
}
var user = new User();
console.log("实例对象", user.login())

// 输出结果:
// 用户名:小鱼神1024
// 密码:12345678

原型、原型对象、实例对象三者互相转化

从原型到原型对象

可以通过 prototype 获取 原型原型对象

console.log("原型到原型对象", User.prototype)
从原型对象到实例对象

可以通过 new 关键字创建 实例对象

console.log("原型对象到实例对象", new User())
从原型对象到原型

可以通过 constructor 获取 原型对象原型

console.log("原型对象到原型", User.prototype.constructor)
console.log("是否为原型", User.prototype.constructor === User)
从原型对象到实例对象

可以先通过 constructor 获取 原型对象原型,再通过 new 关键字创建 实例对象

console.log("原型对象到实例对象", new User.prototype.constructor())
从实例对象到原型对象

先通过 __proto__ 或者 Object.getPrototypeOf 获取 实例对象原型对象

console.log("实例对象到原型对象1", user.__proto__)
console.log("实例对象到原型对象2", Object.getPrototypeOf(user))
console.log("是否为原型对象", user.__proto__ === User.prototype)
console.log("是否为原型对象", Object.getPrototypeOf(user) === User.prototype)
从实例对象到原型

先通过 __proto__ 或者 Object.getPrototypeOf 获取 实例对象原型对象,再通过 constructor 获取 原型对象原型

console.log("实例对象到原型1", user.__proto__.constructor)
console.log("实例对象到原型2", Object.getPrototypeOf(user).constructor)
console.log("是否为原型", user.__proto__.constructor === User)
console.log("是否为原型", Object.getPrototypeOf(user).constructor === User)

总结

  • 原型:User,是一个函数。
  • 原型对象:User.prototype,通过 prototype 得到原型对象。
  • 实例对象:new User(),通过 new 关键字得到实例对象。

案例

阅读到这里,文章开头的问题能独立解决了吗?

我们一起分析一下吧!

navigator 其实可以理解为 实例对象Navigator 可以理解为 原型

Object.getOwnPropertyDescriptor(window.navigator, "userAgent") 可以理解为:获取 window.navigatoruserAgent 属性的描述符。

在浏览器中,它返回的是 undefined,但是通过 navigator.userAgent 又可以拿到值。说明 userAgent 不是 window.navigator 本身的属性,而是 window.navigator原型 的属性。

所以,我们可以通过修改原型对象 navigator.__proto__.userAgent 来修改 Navigator 原型的值,从而间接修改 navigator.userAgent 的值。

js补环境系列-原型、原型对象、实例对象

这样问题就解决了!

有任何问题欢迎留言讨论!或者加v讨论!

创作不易,动动您发财的小手,点赞关注一波,支持我创作更多对您有帮助的文章!

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

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

相关文章

最大文件句柄数

优质博文:IT-BLOG-CN 灵感来源 一、什么是文件句柄 文件句柄File Handle是操作系统中用于访问文件的一种数据结构,通常是一个整数或指针。文件句柄用于标识打开的文件,每个打开的文件都有一个唯一的文件句柄。 它们是对文件、网络套接字或…

商业数据分析思维的培训PTT制作大纲分享

商业数据分析思维的培训PTT制作大纲: 基本步骤: 明确PPT的目的和主题 收集并整理相关内容资料 构思并确定PPT的框架大纲 编写PPT的内容文字 插入图片、图表等视觉元素 设计PPT的版式和模板 排练并修改PPT 输出并备份最终版本 目的:数据思维培养; 主题:商业数据分…

【TensorRT】Yolov5-DeepSORT 目标跟踪

Yolov5-DeepSORT-TensorRT 本项目是 Yolo-DeepSORT 的 C 实现,使用 TensorRT 进行推理 🚀🚀🚀 开源地址:Yolov5_DeepSORT_TensorRT,求 star⭐ ~ 引言 ⚡ 推理速度可达25-30FPS,可以落地部署&…

PriorityQueue 阅读记录

1、前言 1、优先队列,底层通过数组来构造树(二叉树) 来实现的。 2、默认是最小堆(取出来的是最小值),可以通过传入一个比较器 comparator 来构造一个最大堆。 3、传入的参数不能为空,否则抛出NPE问题。 4、最大堆的…

git自动pull同步远程若干分支与本地若干分支

git自动pull同步远程若干分支与本地若干分支 假设远程代码仓库有100个分支,而本地只有10个本地分支与远程分支一一对应,现在要保持本地的这个10个分支与远程一致,最笨的方法是checkout到每个分支,然后一个一个的 git pull origin…

第11章 规划过程组(四)(11.4规划质量管理)

第11章 规划过程组(四)11.4规划质量管理,在第三版教材第412~414页; 文字图片音频方式 第一个知识点:工具与技术 1、数据分析(重要知识点) 成本效益分析 确定质量活动的可能成本与预期效益&a…

HTML2048小游戏

源代码在效果图后面 效果图 源代码 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>2048 Game&l…

Qt Creator的好用的功能

&#xff08;1&#xff09;ctrlf&#xff1a; 在当前文档进行查询操作 &#xff08;2&#xff09;f3: 找到后&#xff0c;按f3&#xff0c;查找下一个 &#xff08;3&#xff09;shiftf3: 查找上一个 右键菜单&#xff1a; (4)f4&#xff1a;在…

【海外云手机】静态住宅IP集成解决方案

航海大背景下&#xff0c;企业和个人用户对于网络隐私、稳定性以及跨国业务的需求日益增加。静态住宅IP与海外云手机的结合&#xff0c;提供了一种创新的集成解决方案&#xff0c;能够有效应对这些需求。 本篇文章分为三个部分&#xff1b;静态住宅优势、云手机优势、集成解决…

FPGA资源容量

Kintex™ 7 https://www.amd.com/zh-tw/products/adaptive-socs-and-fpgas/fpga/kintex-7.html#product-table AMD Zynq™ 7000 SoC https://www.amd.com/en/products/adaptive-socs-and-fpgas/soc/zynq-7000.html#product-table AMD Zynq™ UltraScale™ RFSoC 第一代 AMD Z…

对象存储解决方案:高性能分布式对象存储系统MinIO

文章目录 引言I 自动化数据管理界面1.1 图形用户界面:GUI1.2 命令行界面:MinIO CLI1.3 应用程序编程接口:MinIO APIII 部署集成2.1 静态端口分配2.2 将NGINX用作反向代理,配置负载。III 基础概念3.1 为什么是对象存储?3.2 MinIO支持哪些系统拓扑结构?3.3 时间同步3.4 存储…

react学习——28react-redux实现多组件共享数据(精简版)

1、目录结构 2、containers/Count/index.js import {createIncrementAction, createDecrementAction, createIncrementAsyncAction} from ../../redux/action/count //引入conect用于链接UI组件与redux import {connect} from react-redux import React, {Component} from &qu…

UML面向对象分析与设计

UML不是OOA/D&#xff0c;也不是方法&#xff0c;它仅仅只是一种图形表示法如果不掌握对象思想&#xff0c;那么UML或任何case工具(如ROSE)将毫无意义 我们需要一种用于〇OA/D的语言&#xff0c;这既是一种思考的工具&#xff0c;也是一种沟通的形式。因此&#xff0c;我们将在…

Python | Leetcode Python题解之第240题搜索二维矩阵II

题目&#xff1a; 题解&#xff1a; class Solution:def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:m, n len(matrix), len(matrix[0])x, y 0, n - 1while x < m and y > 0:if matrix[x][y] target:return Trueif matrix[x][y] > tar…

前端基础之JavaScript学习——变量、数据类型、类型转换

大家好&#xff0c;我是来自CSDN的博主PleaSure乐事&#xff0c;今天我们开始有关JS的学习&#xff0c;希望有所帮助并巩固有关前端的知识。 我使用的编译器为vscode&#xff0c;浏览器使用为谷歌浏览器&#xff0c;使用webstorm或其他环境效果几乎一样&#xff0c;使用系统自…

搞清c++中的队列(queue)以及双端队列(deque),以及常用的接口!

1. 队列 概念&#xff1a;Queue是一种先进先出(First In First Out,FIFO)的数据结构&#xff0c;它有两个出口 特征&#xff1a; 队列容器允许从一端新增元素&#xff0c;从另一端移除元素 队列中只有队头和队尾才可以被外界使用&#xff0c;因此队列不允许有遍历行为 队列…

【React Hooks原理 - forwardRef、useImperativeHandle】

概述 上文我们聊了useRef的使用和实现&#xff0c;主要两个用途&#xff1a;1、用于持久化保存 2、用于绑定dom。 但是有时候我们需要在父组件中访问子组件的dom或者属性/方法&#xff0c;而React中默认是不允许父组件直接访问子组件的dom的&#xff0c;这时候就可以通过forwa…

进程通信(3): System V IPC

System IPC包括System V消息队列&#xff0c;System V信号量&#xff0c;System V共享内存区。 System V IPC使用一个key&#xff08;key_t&#xff09;作为他们名字&#xff0c;这个值由ftok函数通过路径名和一个id生成。 客户和服务器通过在路径名和id达成一致&#xff0c;双…

解决网页中的 video 标签在移动端浏览器(如百度访问网页)视频脱离文档流播放问题

问题现象 部分浏览器视频脱离文档流&#xff0c;滚动时&#xff0c;视频是悬浮出来&#xff0c;在顶部播放 解决方案 添加下列属性&#xff0c;可解决大部分浏览器的脱离文档流的问题 <videowebkit-playsinline""playsInlinex5-playsinlinet7-video-player-t…

pico+unity3d开启彩色透视

1、点击游戏对象、点击XR、点击添加XR Origin&#xff0c;并把自带的摄像对象删除 2、添加脚本 using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.XR.PXR;//引入xr对象 public class toushi : MonoBehaviour {// Start is called…