首页 > 其他分享 >js hook技术的感想

js hook技术的感想

时间:2023-08-26 19:12:26浏览次数:49  
标签:function log 畜生 感想 js hook speek Animal new

最新老婆准备找工作,找了一些js的面试题,有些不懂,其中有一个问啥是原型啥是原型链, 直接把我问懵逼了,接触js这么多年, 没有真正了解过某种用法或者技术的学名是啥。一帮所谓学者还真是取了漂亮名。 为此百度了一番,大部分博客写的一般般, 太过理论,我来点实际的

定一个类目前有两种方式:

函数式:

function A(){ this.a = 1; }
A.log = function (){}
A.prototype.log = function(){}
// 我刻意写成一样,都叫log

类式:

class A {
  constructor() {this.a = 1;}
  static log() {}
  log() {}
}

第二种方式其实是第一种方式的语法糖,只是写法不同,类底层逻辑的其实还是第一种, 但是没有人证明过, 我决定证明一下:

 两者类的定义方式我交换了顺序,看上面的图里错误信息堆栈一摸一样,编译器碰到class A, 使用compileFunction去编译的, 这一点就足以证明class写法是第一种的漂亮写法。   

还没结束,再看这个样例:

通过这个例子,通过class 写的类,必须要使用new。 可以证明,class A也就仅仅只是function A 定义类的方式一种漂亮写法, 并不完全等价。事实上仅仅是在实现类方面一样,但是function并不仅限类的实现

再看这个样例:

function Animal(){
    this.name = '动物';
    this.speek = function (){
        console.log('你是畜生');
    }
    return this;
}
Animal.speek = function(){
    console.log('我是畜生-通过类名调用');
}

Animal.prototype.speek = function(){
    console.log('我是畜生-通过实例调用');
}

new Animal().speek();   // 你是畜生
Animal().speek();       // 你是畜生
Animal.speek();         // 我是畜生-通过类名调用

Animal().name;          // 动物
Animal() === Animal();  // true

Animal()函数里有一个this, 有的人可能不知道this是啥,this其实表示运行的当前环境。 记住一句话,谁在调用this就代表谁。

如果通过new Animal()写的, 这个this就是实例对象,new方式底层构造函数v8调用的

如果是通过Animal()写的,this表示全局对象,因为是在文件根调用的。

如何输出内容 我是畜生-通过类名调用?

要想输出它就必须清楚这个方法存放在哪个object中?

上面的代码其实设计有4种Object

第一种Object是 global

第二种Object是 new Animal()

第三种Object是 Animal.prototype

第四种Object是 Animal

new Animal().speek 没有走原型里的方法,因为它自己定义了speek。

通过对象.方法名去调用的时候,v8有一个查找路径,优先找自己实例的方式,没有就去原型里找,原型里还有原型,一层一层往上找, 直到Object对象为止,这个是一切对象的超类。

我自己定义了speek, 还想使用原型方法, 直接上干货

  1. 删除自己的定义,然后再调用
const anim = new Animal(); 
delete anim.speek;
anim.speek();// 我是畜生-通过实例调用
  1. 直接跳过自己的定义的方法
const anim = new Animal(); 
anim.__proto__.speek.call(anim);  // 我是畜生-通过实例调用
  1. 以上两种方式,我破解某些app的时候都用过, 知道底层运行原理,就可以随意hook了
    比如在原来的函数后输出一句话,你才是畜生
const anim = new Animal(); 
const speek = anim.__proto__.speek;
anim.__proto__.speek = function(){
    speek.call(this);
    console.log('你才是畜生');
}
anim.__proto__.speek.call(anim);  // 我是畜生-通过实例调用\n你才是畜生
  1. 现在hook构造函数,之后不管怎么创建对象,都用原型方法一劳永逸
const oldAnimal = Animal;
Animal = function(){// hook
    delete oldAnimal.call(this).speek;
    return this;
}

Animal.prototype = oldAnimal.prototype;

const ani2 = new Animal();
ani2.speek();
  1. 超炫酷玩js
// 修改所有类的顶头上司
Object.prototype.log = function(...args){
    console.log(`${this.name}`, ...args);
}

// 任何log方法, 都走到了超类, 这就是所谓的原型链查找
new Animal().log('你才是畜生');  // 动物 你是畜生
[].log('你才是畜生');  // undefined 你才是畜生
({}).log('你才是畜生');  // undefined 你才是畜生
this.log('你才是畜生');  // undefined 你才是畜生
  1. 输出任何对象的属性和方法, 包括不可遍历属性
function getKeys(obj){
    let keys = {};
    function set(args){
        args.forEach((item) => {
            keys[item] = 1;
        });
    }

    function _(obj){
        if(!obj ){
            return;
        }

        set(Object.getOwnPropertyNames(obj))
        if(obj.__proto__){
            set(Object.getOwnPropertyNames(obj.__proto__));

            _(obj.__proto__)
        }
    }
    _(obj);
    return Object.keys(keys);
}
  1. js set get hook
    https://www.cnblogs.com/dzqdzq/p/17031252.html

  2. 闭包hook, 理论无法hook原始闭包里的局部变量,下面的代码hook,相当于重新创建了一个闭包。
    有点脱了裤子放屁的感觉,因为完全可以直接hook,而不是使用proxy

function counter() {
    var count = 0;
    return function() {
        return ++count;
    }
}

function hookCounter() {
    const handler = {
        apply: function(target, thisArg, argumentsList) {
            eval(target.toString().replace("++count;", "(count = arguments[0]), count"));
            return counter.apply(thisArg, argumentsList);
        },
    };
    
    return new Proxy(counter, handler);;
}

counter = hookCounter();
var count = counter();
console.log(count(5)); // 输出 5
console.log(count(6)); // 输出 6
console.log(count(7)); // 输出 7
console.log(counter()(10)); // 输出 10

标签:function,log,畜生,感想,js,hook,speek,Animal,new
From: https://www.cnblogs.com/dzqdzq/p/17658810.html

相关文章

  • 轻骑兵使用driver.js踩坑
    1安装哪个版本建议安装0.9.8原版。[email protected]怎么引入、使用不要提成文件,在页面里面使用就可以。vue-page.vuetemplate<el-form-itemprop="username":class="{user:isValidateUserName}"class="username"id="create-post1">...&l......
  • 2023-08-26 关于JSON.stringify会过滤调undefined值的问题 ==》在格式化之前先用type
    今天传参给后端的时候就发现了这么个问题,明明对象里面有这个字段a,但是打印出来死活没有,去掉json格式化后才发现是该值a为undefined,遂百度,故得知该值会被过滤掉。被过滤掉的原因是因为undefined值不符合JSON.stringify的规范。......
  • [JSOI2018] 潜入行动
    题目描述外星人又双叒叕要攻打地球了,外星母舰已经向地球航行!这一次,JYY已经联系好了黄金舰队,打算联合所有JSOIer抵御外星人的进攻。在黄金舰队就位之前,JYY打算事先了解外星人的进攻计划。现在,携带了监听设备的特工已经秘密潜入了外星人的母舰,准备对外星人的通信实施监听。外......
  • JSON字符串的几种格式
    1.JSON数值{“key”:value}{"key":520,"key1":1314}2.JSON字符串{“key”:“value”}{"key":"我爱你","key1":"一生一世"}3.JSON数组{“key”:[value]}{"key":[520,1314]......
  • js 下载流调用浏览器预览 的方法
    //文件预览js下载流调用浏览器预览的方法var$viewblob=function(url,data){constconfig={responseType:'blob',timeout:9999999};$http(url,data,config).then(res=>{constfileRes=res;lettype={type:'application/octet-stream......
  • 报错ValueError: Can't find 'adapter_config.json'
    前言在做组内2030项目时,我具体做的一个工作是对大模型进行LoRA微调,在整个过程中有许多坑,其中有些值得记录的问题,于是便产生了这篇博客。问题我在得到微调好的模型后,需要对模型进行性能测评。在加载模型时,遇到如下报错ValueError:Can'tfind'adapter_config.json'补充:报错......
  • 深入了解Webpack:特性、特点和结合JS混淆加密的实例
    Webpack是现代前端开发中最受欢迎的构建工具之一,其强大的特性和灵活性使得开发者能够更有效地管理和优化项目资源。在本文中,我们将深入探讨Webpack的特性和特点,并结合实例演示如何使用Webpack与JS混淆加密相结合。Webpack的特性和特点1.模块化管理Webpack支持将项目拆分为多个模块......
  • SQLite 3.43 发布,JSON 处理性能提升 2 倍
    SQLite3.43发布,JSON处理性能提升2倍来源:OSCHINA编辑: 局2023-08-2516:58:59 38月26日「源创会」北京站,聊聊AI大模型与底层技术>>> SQLite3.43已正式发布。SQLite是一个C语言库,实现了一个小型、快速、独立、高可靠性、全功能的SQL数据库......
  • js对象操作(object)
    声明对象varcan_args=newObject();对象赋值can_args={"vue":300,"jquery":200……};对象动态赋值(新建属性值)第一种:letkey="id";letvalue=2can_args[key]=value;console.error(can_args);//{"vue":300,"jquery":200,......
  • 大屏读取本地文件-js读取csv文件之FileReader
    <script>functionreadCsv(){constfile=document.getElementById('uploadFile').files[0];if(file.type!="text/csv"){alert("文件类型错误");return;}varreader=newFileReade......