当前位置: 首页 > news >正文

odoo前端js对象的扩展方法

odoo前端js对象的扩展方法

在 Odoo 中,你可以使用两种方法来扩展 JavaScript 对象:extendspatch。这两种方法在功能上有一些区别。

  1. extends 方法:

    • 使用 extends 方法可以创建一个新的 JavaScript 对象,并继承自现有的对象。这意味着你可以在新对象中添加、修改或覆盖现有对象的属性和方法。
    • extends 方法适用于对现有对象进行全面的扩展和修改,以满足特定的需求。你可以通过创建一个新的对象,并在其中添加自定义的属性和方法来实现扩展。
    • 使用 extends 方法时,你需要确保新对象的原型链正确设置,以便正确继承和覆盖现有对象的属性和方法。
  2. patch 方法:

    • 使用 patch 方法可以直接修改现有的 JavaScript 对象,而无需创建新的对象。你可以通过 patch 方法来修改对象的属性和方法,添加新的属性和方法,或者删除现有的属性和方法。
    • patch 方法适用于对现有对象进行局部的修改和调整,以满足特定的需求。你可以直接在现有对象上进行修改,而无需创建新的对象。
    • 使用 patch 方法时,你需要确保正确地定位到要修改的对象,并进行相应的修改操作。

总的来说,extends 方法适用于全面的扩展和修改,而 patch 方法适用于局部的修改和调整。选择使用哪种方法取决于你的具体需求和场景。

1、patch的实现

patch 一个简单的例子

/** @odoo-module **/import { _t } from "@web/core/l10n/translation";
import { patch } from "@web/core/utils/patch";
import { SearchBar } from "@web/search/search_bar/search_bar";patch(SearchBar.prototype, {getPreposition(searchItem) {let preposition = super.getPreposition(searchItem);if (this.fields[searchItem.fieldName].name == 'payment_date') {preposition = _t("until");}return preposition}
});

2、patch.js

先学习一下object对象,再来学习patch.js

patch对象的原型,调用了很多Object的静态方法,原则上就是在原型对象上动态增加或者替换新的属性。

        // Replace the old property by the new one.Object.defineProperty(objToPatch, key, newProperty);

附录: patch.js 源文件

/** @odoo-module **//***  @typedef {{*      originalProperties: Map<string, PropertyDescriptor>;*      skeleton: object;*      extensions: Set<object>;*  }} PatchDescription*//** @type {WeakMap<object, PatchDescription>} */
const patchDescriptions = new WeakMap();/*** Create or get the patch description for the given `objToPatch`.* @param {object} objToPatch* @returns {PatchDescription}*/
function getPatchDescription(objToPatch) {if (!patchDescriptions.has(objToPatch)) {patchDescriptions.set(objToPatch, {originalProperties: new Map(),skeleton: Object.create(Object.getPrototypeOf(objToPatch)),extensions: new Set(),});}return patchDescriptions.get(objToPatch);
}/*** @param {object} objToPatch* @returns {boolean}*/
function isClassPrototype(objToPatch) {// class A {}// isClassPrototype(A) === false// isClassPrototype(A.prototype) === true// isClassPrototype(new A()) === false// isClassPrototype({}) === falsereturn Object.hasOwn(objToPatch, "constructor") && objToPatch.constructor?.prototype === objToPatch;
}/*** Traverse the prototype chain to find a potential property.* @param {object} objToPatch* @param {string} key* @returns {object}*/
function findAncestorPropertyDescriptor(objToPatch, key) {let descriptor = null;let prototype = objToPatch;do {descriptor = Object.getOwnPropertyDescriptor(prototype, key);prototype = Object.getPrototypeOf(prototype);} while (!descriptor && prototype);return descriptor;
}/*** Patch an object** If the intent is to patch a class, don't forget to patch the prototype, unless* you want to patch static properties/methods.** @template T* @template {T} U* @param {T} objToPatch The object to patch* @param {U} extension The object containing the patched properties* @returns {() => void} Returns an unpatch function*/
export function patch(objToPatch, extension) {if (typeof extension === "string") {throw new Error(`Patch "${extension}": Second argument is not the patch name anymore, it should be the object containing the patched properties`);}const description = getPatchDescription(objToPatch);description.extensions.add(extension);const properties = Object.getOwnPropertyDescriptors(extension);for (const [key, newProperty] of Object.entries(properties)) {const oldProperty = Object.getOwnPropertyDescriptor(objToPatch, key);if (oldProperty) {// Store the old property on the skeleton.Object.defineProperty(description.skeleton, key, oldProperty);}if (!description.originalProperties.has(key)) {// Keep a trace of original property (prop before first patch), useful for unpatching.description.originalProperties.set(key, oldProperty);}if (isClassPrototype(objToPatch)) {// A property is enumerable on POJO ({ prop: 1 }) but not on classes (class A {}).// Here, we only check if we patch a class prototype.newProperty.enumerable = false;}if ((newProperty.get && 1) ^ (newProperty.set && 1)) {// get and set are defined together. If they are both defined// in the previous descriptor but only one in the new descriptor// then the other will be undefined so we need to apply the// previous descriptor in the new one.const ancestorProperty = findAncestorPropertyDescriptor(objToPatch, key);newProperty.get = newProperty.get ?? ancestorProperty?.get;newProperty.set = newProperty.set ?? ancestorProperty?.set;}// Replace the old property by the new one.Object.defineProperty(objToPatch, key, newProperty);}// Sets the current skeleton as the extension's prototype to make// `super` keyword working and then set extension as the new skeleton.description.skeleton = Object.setPrototypeOf(extension, description.skeleton);return () => {// Remove the description to start with a fresh base.patchDescriptions.delete(objToPatch);for (const [key, property] of description.originalProperties) {if (property) {// Restore the original property on the `objToPatch` object.Object.defineProperty(objToPatch, key, property);} else {// Or remove the property if it did not exist at first.delete objToPatch[key];}}// Re-apply the patches without the current one.description.extensions.delete(extension);for (const extension of description.extensions) {patch(objToPatch, extension);}};
}

相关文章:

odoo前端js对象的扩展方法

odoo前端js对象的扩展方法 在 Odoo 中&#xff0c;你可以使用两种方法来扩展 JavaScript 对象&#xff1a;extends 和 patch。这两种方法在功能上有一些区别。 extends 方法&#xff1a; 使用 extends 方法可以创建一个新的 JavaScript 对象&#xff0c;并继承自现有的对象。这…...

力扣双周赛 -- 117(容斥原理专场)

class Solution { public:long long c2(long long n){return n > 1? n * (n - 1) / 2 : 0;}long long distributeCandies(int n, int limit) {return c2(n 2) - 3 * c2(n - limit 1) 3 * c2(n - 2 * limit) - c2(n - 3 * limit - 1);} };...

基于Rabbitmq和Redis的延迟消息实现

1 基于Rabbitmq延迟消息实现 支付时间设置为30&#xff0c;未支付的消息会积压在mq中&#xff0c;给mq带来巨大压力。我们可以利用Rabbitmq的延迟队列插件实现消息前一分钟尽快处理 1.1定义延迟消息实体 由于我们要多次发送延迟消息&#xff0c;因此需要先定义一个记录消息…...

Masked Relation Learning for DeepFake Detection

一、研究背景 1.现有deepfake检测方法大多关注于局部伪影或面部不协调&#xff0c;较少挖掘局部区域间的关系。 2.现有关系挖掘类的工作往往忽略了关系信息的传播。 3.遮挡建模在减轻信息冗余的同时促进高级语义信息&#xff08;诱导性偏差较小&#xff09;的挖掘&#xff0c;有…...

R语言爬虫程序自动爬取图片并下载

R语言本身并不适合用来爬取数据&#xff0c;它更适合进行统计分析和数据可视化。而Python的requests&#xff0c;BeautifulSoup&#xff0c;Scrapy等库则更适合用来爬取网页数据。如果你想要在R中获取网页内容&#xff0c;你可以使用rvest包。 以下是一个简单的使用rvest包爬取…...

2023年10月国产数据库大事记-墨天轮

本文为墨天轮社区整理的2023年10月国产数据库大事件和重要产品发布消息。 目录 10月国产数据库大事记 TOP1010月国产数据库大事记&#xff08;时间线&#xff09;产品/版本发布兼容认证代表厂商大事记厂商活动排行榜新增数据库相关资料 10月国产数据库大事记 TOP10 10月国产…...

Linux内核分析(十四)--内存管理之malloc、free 实现原理

目录 一、引言 二、malloc实现方式 ------>2.1、动态内存分配的系统调用:brk / sbrk ------>2.2、malloc实现思路 ------------>2.2.1、最佳适应法 ------------>2.2.2、最差适应法 ------------>2.2.3、首次适应法 ------------>2.2.4、下一个适应…...

Hive函数

1. Hive 内置运算符 整体上&#xff0c;Hive 支持的运算符可以分为三大类&#xff1a;关系运算、算术运算、逻辑运算。 官方参考文档&#xff1a;LanguageManual UDF - Apache Hive - Apache Software Foundation 也可以使用下述方式查看运算符的使用方式&#xff1a; -- 显…...

教资笔记(目录)

目录 中小学教资笔记总结中学教资小学教资小学中学科一《综合素质》&#xff08;通用&#xff09;&#xff1a;考情分析&#xff1a;学习笔记 小学科二《教育知识与能力》&#xff1a;考情分析&#xff1a;学习笔记&#xff1a; 中小学教资笔记总结 2023.9.16教资考试 笔试成绩…...

np.repeat()的注意事项

对于一个shape为&#xff08;3, 2&#xff09;的矩阵a&#xff0c; b a.repeat(9, axis1)。 那b[:, :9]是相同的&#xff0c;b[:, 9:]是相同的&#xff0c;意见 a np.random.rand(3, 2) b a.repeat(9, axis1) np.all(b[:, 0] b[:, 1]), np.all(b[:, 0] b[:, 9]) Out: (Tr…...

239. 滑动窗口最大值

239. 滑动窗口最大值 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a;错误经验吸取 原题链接&#xff1a; 239. 滑动窗口最大值 https://leetcode.cn/problems/sliding-window-maximum/description/ 完成情况&#xff1a; 解题思路&…...

c++ barrier 使用详解

c barrier 使用详解 std::barrier c20 头文件 #include <barrier>。作用&#xff1a;一般被用来协调多个线程&#xff0c;在所有线程都到达屏障点之后&#xff0c;才允许它们继续执行&#xff0c;对于需要线程间同步的并行算法和任务来说非常有用。使用步骤&#xff1a…...

c# 接口

c#接口 namespace demo1 {/// <summary>/// 接口使用interface关键字进行定义/// 接口中只能声明方法不能定义&#xff0c;也就是说声明的方法不能有方法体。/// 接口不能包含常量、字段、运算符、实例构造函数、析构函数或类型&#xff0c;不能包含静态成员。由于不能有…...

1、NPC 三电平SVPWM simulink仿真

1、SVPWM时间计算函数&#xff0c;是从matlab的SVPWM3L_TimingCalculation.p文件中反汇编出来的函数&#xff1a; function [TgABC_On ,TgABC_Off ,Sn ]SVPWM3L_TimingCalculation_frompfile (Vref ,DeltaVdc ,Fsw ) %#codegen %coder .allowpcode (plain ); TgABC_On [0 ,0 ,…...

JAVA对象列表强转失败,更好的方法

JAVA将无法强转的list泛型对象使用JSON工具类转换为list类 List<DiskUseRateVo> list JSON.parseArray(JSON.toJSONString(httpGet(url).getContent()), DiskUseRateVo.class);之前一直强转发现后续list.get(0)报错&#xff0c;用JSON解决了问题。...

2023最新版本 从零基础入门C++与QT(学习笔记) -5- 动态内存分配(new)

&#x1f38f;C的动态内存要比C方便 &#x1f384;注意C申请内存的时候可以直接的初始化&#xff01;&#xff01;&#xff01; &#x1f384;格式&#xff08;申请一块内存&#xff09; &#x1f388;new(关键字) 变量类型 &#x1f384;格式&#xff08;申请多块内存&am…...

asp.net校园招聘管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net 校园招聘管理系统是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言开发 应用技术&#xff1a;asp.net c#s…...

flink的键值分区状态自动过期ttl配置

背景 flink的状态清理之前一直都是通过处理函数的ontimer设置定时器的方式清理掉那些无用的状态&#xff0c;但是这种方式容易出错而且代码也不优雅&#xff0c;使用flink提供的状态ttl的方式可以解决这个问题 flink键值分区状态ttl设置 文件系统/基于内存的状态后端的ttl设…...

解决Mac配置maven环境后,关闭终端后环境失效的问题(适用于所有终端关闭后环境失效的问题)

目录 问题的原因 解决方式一、每次打开终端时输入&#xff1a;"source ~/.bash_profile"&#xff0c;这个方式比较繁琐 解决方式二、我们终端输入"vim ~/.zshrc"打开".zshrc"文件 1、我们输入以下代码&#xff1a; 2、首先需要按 " i…...

springboot运行jar包,实现复制jar包resources下文件、文件夹(可支持包含子文件夹)到指定的目录

背景&#xff1a; 以jar包运行时&#xff0c;获取文件目录时&#xff0c;会报错&#xff1b; idea运行不会报错。 代码&#xff1a; //复制文件夹到指定路径下 String srcFilePath Thread.currentThread().getContextClassLoader().getResource("").getPath() &…...

【架构师通关】理发店排队 + 车库停车,大白话秒懂“进程状态模型”与“PV操作

兄弟们&#xff0c;操作系统的进程管理一直是软考里最让人头疼的“硬骨头” &#x1f9b4;。什么“阻塞”、“挂起”、“信号量”、“PV操作”&#xff0c;听着就像天书 &#x1f4da;。 但今天&#xff0c;飞哥绝不跟你拽学术名词&#xff01;咱们就通过“去理发店剪个头” &a…...

NSGA-III中的参考点生成与多样性维护机制解析

1. NSGA-III算法中的参考点是什么&#xff1f; 第一次接触NSGA-III算法时&#xff0c;最让我困惑的就是这个"参考点"概念。简单来说&#xff0c;参考点就像是多目标优化问题中的导航灯塔&#xff0c;它们均匀分布在目标空间里&#xff0c;指引算法找到分布均匀的解集…...

深朴智能与生数科技达成深度战略合作,共筑物理世界的通用智能

4月2日&#xff0c;通用具身智能机器人企业北京深朴智能科技有限公司&#xff08;以下简称“深朴智能”&#xff09;与通用世界模型公司北京生数科技有限公司&#xff08;以下简称“生数科技”&#xff09;宣布达成深度战略合作。双方将围绕“通用具身智能大脑”这一核心方向展…...

修改 WindTerm 快捷键配置为Ctrl+V / Ctrl+C

为了让 复制 / 粘贴 的快捷键更符合 Windows 的使用习惯&#xff0c;可以按下面的方法修改 WindTerm 的配置文件。 一、找到配置文件 先进入 WindTerm 的安装目录&#xff0c;然后依次打开&#xff1a; global 文件夹 在该文件夹中找到以下配置文件之一&#xff1a; wind.keyma…...

想找济南市中区靠谱装修施工工艺商家?这家公司值得一探!

26年初&#xff0c;随着济南市中区新盘交付&#xff0c;家装成为许多业主生活中的一件大事。然而&#xff0c;家装市场鱼龙混杂&#xff0c;价格不透明、施工质量参差不齐等问题让不少业主头疼不已。今天&#xff0c;我们就来深入探讨几家本地的装修公司&#xff0c;为大家的家…...

nerdctl 入门指南:从安装到容器管理

1. 为什么选择 nerdctl 管理容器&#xff1f; 如果你已经熟悉 Docker 的命令行工具&#xff0c;那么第一次接触 nerdctl 时会感到非常亲切。作为 containerd 生态中的明星工具&#xff0c;nerdctl 提供了与 Docker CLI 高度兼容的操作体验&#xff0c;但底层却采用了更轻量级的…...

3步解锁Arduino红外遥控:终极实战指南

3步解锁Arduino红外遥控&#xff1a;终极实战指南 【免费下载链接】Arduino-IRremote Infrared remote library for Arduino: send and receive infrared signals with multiple protocols 项目地址: https://gitcode.com/gh_mirrors/ar/Arduino-IRremote 想要让Arduino…...

Notepad--:中文开发者的跨平台文本编辑解决方案

Notepad--&#xff1a;中文开发者的跨平台文本编辑解决方案 【免费下载链接】notepad-- 一个支持windows/linux/mac的文本编辑器&#xff0c;目标是做中国人自己的编辑器&#xff0c;来自中国。 项目地址: https://gitcode.com/GitHub_Trending/no/notepad-- 核心价值&a…...

markdown基础语法及效果演示

[toc] 自动生成目录 文章目录标题二级标题# 标题 一级标题 标题 - 无序列表 无序列表无序列表 # 二级标题 二级标题 代码块&#xff1a; python print(“hello world!”) #代码块 print("hello world!") #代码块>引用 引用 >>二级引用 二级引用 - […...

如何高效实现多尺度时间序列分类:InceptionTime深度学习框架深度解析

如何高效实现多尺度时间序列分类&#xff1a;InceptionTime深度学习框架深度解析 【免费下载链接】InceptionTime 项目地址: https://gitcode.com/gh_mirrors/in/InceptionTime 时间序列分类是金融风控、工业监测、医疗诊断等领域的核心任务&#xff0c;InceptionTime作…...