2024-08-24

在JavaScript中,实现一个类似于String.prototype.trim()的功能,可以去除字符串两端的空格。以下是一个简单的实现:




String.prototype.myTrim = function() {
  // 使用正则表达式匹配字符串两端的空格
  return this.replace(/^\s+|\s+$/g, '');
};
 
// 示例使用
const str = "  Hello, World!  ";
const trimmedStr = str.myTrim();
console.log(trimmedStr); // 输出: "Hello, World!"

这段代码定义了String.prototype.myTrim方法,通过正则表达式/^\s+|\s+$/g匹配字符串开始和结束的空白字符(包括空格、制表符等),并将其替换为空字符串,从而实现去除两端空格的效果。

2024-08-24

在uni-app项目中,你可以在项目根目录下的manifest.json文件中设置全局变量,然后在main.js中引入并设置到Vue.prototype上,这样在应用的任何页面都可以通过this访问这些全局变量。

  1. 打开manifest.json文件。
  2. manifest.jsonh5节点下,或者根节点下(全局生效),添加你的后端地址配置:



{
  // ... 其他配置
  "global": {
    "apiUrl": "https://your-backend-url.com/api/"
  }
}
  1. 打开main.js文件,引入全局变量并设置到Vue.prototype上,以便于全局访问:



// main.js
Vue.prototype.$apiUrl = manifest.global.apiUrl;
 
// 或者如果你不想在每个页面单独引入manifest.json,可以在main.js中直接设置
Vue.prototype.$apiUrl = "https://your-backend-url.com/api/";
  1. 在应用的任何页面或组件中,你可以通过this.$apiUrl来访问后端访问地址:



// 例如,在某个页面的methods中
methods: {
  fetchData() {
    const url = this.$apiUrl + 'some-endpoint';
    // 使用url进行后续的网络请求操作
  }
}

确保在使用这些全局变量之前,已经在main.js中正确设置了它们。这样你就可以在config.js中设置后端访问地址,并在应用的任何页面通过全局变量来使用它了。

2024-08-24

在JavaScript中,"浅拷贝"和"深拷贝"是两种不同的复制对象的方法。浅拷贝只复制了对象的最外层,而深拷贝则会递归复制所有层级。

浅拷贝的实现方法:

  1. 对象展开运算符(...
  2. Object.assign()
  3. 手动循环属性

深拷贝的实现方法:

  1. 使用JSON.parse(JSON.stringify())(注意,这种方法不能复制包含循环引用的对象或者函数等无法序列化的属性)
  2. 递归复制(手动实现深拷贝)

以下是实现浅拷贝和深拷贝的示例代码:

浅拷贝示例:




// 使用对象展开运算符
const shallowCopy1 = { ...originalObject };
 
// 使用Object.assign()
const shallowCopy2 = Object.assign({}, originalObject);
 
// 手动循环属性
const shallowCopy3 = {};
for (let key in originalObject) {
  shallowCopy3[key] = originalObject[key];
}

深拷贝示例:




// 使用JSON.parse(JSON.stringify())
const deepCopy1 = JSON.parse(JSON.stringify(originalObject));
 
// 递归复制
const deepCopy2 = recursiveCopy(originalObject);
 
function recursiveCopy(obj) {
  if ((obj === null) || (typeof obj !== 'object')) {
    return obj;
  }
 
  if (obj instanceof Date) {
    return new Date(obj.getTime());
  }
 
  if (obj instanceof Array) {
    return obj.reduce((arr, item, i) => {
      arr[i] = recursiveCopy(item);
      return arr;
    }, []);
  }
 
  if (obj instanceof Object) {
    return Object.keys(obj).reduce((newObj, key) => {
      newObj[key] = recursiveCopy(obj[key]);
      return newObj;
    }, {});
  }
}

注意:JSON.parse(JSON.stringify())的方法存在局限性,不能复制函数、undefined、循环引用等。因此,在复杂场景下,通常推荐使用递归复制的方式来创建深拷贝。

2024-08-24

在前端使用pako.js压缩字符串,然后在后端使用Java解压,你可以使用Java的Inflater类来解压经过pako.js压缩的数据。以下是一个简单的例子:

前端(JavaScript):




const pako = require('pako');
 
// 假设这是你通过pako压缩过的数据
const compressedData = pako.deflate('这是一个压缩的字符串', { to: 'string' });
 
// 将compressedData发送到服务器

后端(Java):




import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
 
public class Decompressor {
    public static String decompress(String compressedStr) {
        byte[] compressedBytes = Base64.getDecoder().decode(compressedStr);
        ByteArrayInputStream bis = new ByteArrayInputStream(compressedBytes);
        Inflater inflater = new Inflater();
        ByteArrayOutputStream bos = new ByteArrayOutputStream(compressedBytes.length);
 
        try {
            byte[] buffer = new byte[1024];
            int len;
            inflater.setInput(bis);
            while (!inflater.needsInput()) {
                len = inflater.inflate(buffer);
                if (len <= 0) {
                    break;
                }
                bos.write(buffer, 0, len);
            }
            bis.close();
            inflater.end();
 
            return new String(bos.toByteArray(), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
 
    public static void main(String[] args) {
        String compressedStr = "eJzT0yMAAGTvBe8="; // 这里应该是前端发送过来的压缩数据
        String decompressedStr = decompress(compressedStr);
        System.out.println(decompressedStr);
    }
}

确保前端发送到服务器的数据是Base64编码的,并且在Java端使用相同的编码方式来解码。解压后的字符串应该是原始的压缩字符串。

2024-08-24

以下是使用Java、Python、C++和JavaScript实现的约瑟夫环算法的代码示例:

Java版本:




public class JosephusGame {
    public static void josephusGame(int n, int k) {
        LinkedList<Integer> circle = new LinkedList<>();
        for (int i = 1; i <= n; i++) {
            circle.add(i);
        }
 
        int idx = 0;
        while (circle.size() > 1) {
            idx = (idx + k - 1) % circle.size();
            circle.remove(idx);
        }
 
        System.out.println("最后剩下的人是:" + circle.get(0));
    }
 
    public static void main(String[] args) {
        josephusGame(5, 3); // 例如,n = 5,k = 3的情况
    }
}

Python版本:




class JosephusGame:
    def josephus_game(self, n, k):
        circle = list(range(1, n + 1))
        while len(circle) > 1:
            idx = (idx + k - 1) % len(circle)
            del circle[idx]
        print(f"最后剩下的人是:{circle[0]}")
 
jg = JosephusGame()
jg.josephus_game(5, 3)  # 例如,n = 5,k = 3的情况

C++版本:




#include <iostream>
#include <list>
 
void josephusGame(int n, int k) {
    std::list<int> circle(n);
    std::iota(circle.begin(), circle.end(), 1);
 
    auto it = circle.begin();
    while (circle.size() > 1) {
        for (int i = 0; i < k - 1; ++i) {
            ++it;
            if (it == circle.end()) {
                it = circle.begin();
            }
        }
        auto next_it = ++it;
        if (next_it == circle.end()) {
            next_it = circle.begin();
        }
        circle.erase(it);
        it = next_it;
    }
 
    std::cout << "最后剩下的人是:" << *it << std::endl;
}
 
int main() {
    josephusGame(5, 3); // 例如,n = 5,k = 3的情况
    return 0;
}

JavaScript版本:




function josephusGame(n, k) {
    let circle = Array.from({ length: n }, (_, i) => i + 1);
 
    let idx = 0;
    while (circle.length > 1) {
        idx = (idx + k - 1) % circle.length;
        circle.splice(idx, 1);
    }
 
    console.log(`最后剩下的人是:${circle[0]}`);
}
 
josephusGame(5, 3); // 例如,n = 5,k = 3的情况

以上代码实现了约瑟夫环的核心功能,并在主函数中提供了使用例子。

2024-08-24

题目:模拟数据序列化传输

在华为OD机试中,您可能会遇到一些关于数据序列化和反序列化的问题。这些问题通常涉及到将数据结构转换为可以在网络上传输的格式,或者从接收到的数据中恢复原始的数据结构。

以下是一个简单的例子,演示如何在Java和JavaScript中实现简单的数据序列化和反序列化。

Java 版本:




public class DataSerializer {
    public static byte[] serialize(int[] data) {
        byte[] bytes = new byte[data.length];
        for (int i = 0; i < data.length; i++) {
            bytes[i] = (byte) data[i];
        }
        return bytes;
    }
 
    public static int[] deserialize(byte[] bytes) {
        int[] data = new int[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            data[i] = bytes[i];
        }
        return data;
    }
 
    public static void main(String[] args) {
        int[] data = {1, 2, 3, 4, 5};
        byte[] serializedData = serialize(data);
        int[] deserializedData = deserialize(serializedData);
        // 打印反序列化后的数据
        for (int i : deserializedData) {
            System.out.print(i + " ");
        }
    }
}

JavaScript 版本:




function serialize(data) {
    const bytes = new Uint8Array(data.length);
    for (let i = 0; i < data.length; i++) {
        bytes[i] = data[i];
    }
    return bytes;
}
 
function deserialize(bytes) {
    const data = new Array(bytes.length);
    for (let i = 0; i < bytes.length; i++) {
        data[i] = bytes[i];
    }
    return data;
}
 
const data = [1, 2, 3, 4, 5];
const serializedData = serialize(data);
const deserializedData = deserialize(serializedData);
// 打印反序列化后的数据
console.log(...deserializedData);

在这两个示例中,我们定义了一个整数数组,并展示了如何将其序列化为字节数组以及如何从字节数组反序列化回整数数组。这是数据序列化和反序列化的基本概念,可以根据实际需求进行扩展和复杂化。

2024-08-24



cmake_minimum_required(VERSION 3.13)
project(my_project)
 
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
# 设置Emscripten工具链变量
set(EMSCRIPTEN_ROOT "/path/to/emsdk/upstream/emscripten")
set(CMAKE_TOOLCHAIN_FILE "${EMSCRIPTEN_ROOT}/cmake/Modules/Platform/Emscripten.cmake")
 
# 设置Emscripten编译选项
set(EMSCRIPTEN_OPTIMIZATION -O3)
set(EMSCRIPTEN_LINK_OPTIMIZATION "${EMSCRIPTEN_OPTIMIZATION}")
set(EMSCRIPTEN_CODE_GEN_OPTIMIZED ON)
 
# 设置Emscripten编译标志
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s DEMANGLE_SUPPORT=1")
 
# 添加源代码文件
file(GLOB SOURCE_FILES "src/*.cpp")
file(GLOB HEADER_FILES "include/*.h")
 
# 添加wasm-bindgen生成的typescript绑定
file(GLOB BINDGEN_FILES "src/*_bg.js")
 
# 创建目标wasm文件
add_custom_command(
    OUTPUT ${CMAKE_BINARY_DIR}/my_project.wasm
    COMMAND emcc ${SOURCE_FILES} ${HEADER_FILES} ${BINDGEN_FILES} -o ${CMAKE_BINARY_DIR}/my_project.js -s WASM=1 -s SIDE_MODULE=1
    DEPENDS ${SOURCE_FILES} ${HEADER_FILES} ${BINDGEN_FILES}
)
 
# 添加自定义目标
add_custom_target(run_project ALL
    COMMAND emrun --no_browser --port 8080 ${CMAKE_BINARY_DIR}/my_project.html
)

这个示例CMakeLists.txt文件展示了如何设置Emscripten工具链,并使用add_custom_command来编译C++项目为WebAssembly和相关的JavaScript文件。它还演示了如何添加一个自定义目标来使用emrun运行项目。注意,这里假设你已经安装了Emscripten SDK,并且将/path/to/emsdk/upstream/emscripten替换为你的实际Emscripten SDK路径。

2024-08-24

报错问题:在使用Vite创建的Vue 3项目中,无法在页面上正确引用位于public目录下的JavaScript文件。

可能原因及解决方法:

  1. 路径错误:确保在<script>标签中正确引用public目录下的文件路径。例如,如果你有一个public/js/example.js文件,你应该使用以下路径引用它:



<script src="/js/example.js"></script>

注意:Vite服务器会将public目录作为一个静态文件服务的根目录,因此不需要在路径前加上/src

  1. 缓存问题:Vite可能因为缓存问题而无法正确加载public目录下的文件。尝试清除缓存后重新启动服务器:



npm run dev

或者,如果你使用的是Yarn,则运行:




yarn dev
  1. 文件引用语法:确保没有语法错误,比如拼写错误或者错误的文件扩展名。
  2. 文件加载顺序:如果页面在public文件夹的js文件之前加载,那么可能会出现问题。确保在需要使用该js文件的地方,该文件已经加载完毕。

如果以上方法都不能解决问题,请提供更详细的错误信息,以便进一步诊断。

2024-08-24

在uniapp中引入线上的JS文件,可以通过以下步骤进行:

  1. index.html中使用<script>标签引入线上的JS文件。
  2. 使用<script>标签的src属性指向线上的JS文件地址。

例如,如果你想引入一个线上的JS库,如https://example.com/library.js,你可以在index.html中添加如下代码:




<script src="https://example.com/library.js"></script>

如果你需要在Vue的生命周期钩子或者其他组件方法中使用这个JS库,确保在onLoadcreated钩子中进行调用,以确保库在你调用它之前已经加载完成。




export default {
  onLoad() {
    // 确保库已加载完成后再使用其功能
    if (window.LibraryFunction) {
      window.LibraryFunction();
    }
  }
}

请注意,由于跨域限制,如果线上JS文件不支持CORS,你可能会遇到安全策略问题。在这种情况下,你可能需要服务器端的配置来解决这个问题。

2024-08-24



// 假设我们有一个列表,我们想要为每个列表项添加点击事件
var list = document.getElementById('myList');
 
// 传统的方式为每个列表项添加事件监听
var items = list.getElementsByTagName('li');
for (var i = 0; i < items.length; i++) {
    items[i].addEventListener('click', function(e) {
        console.log('你点击了:' + e.target.innerHTML);
    });
}
 
// 使用事件委托的方式,减少事件监听的数量
list.addEventListener('click', function(e) {
    if (e.target && e.target.nodeName === 'LI') {
        console.log('你点击了:' + e.target.innerHTML);
    }
});

这个例子展示了传统的为每个列表项分别添加事件监听的方法,以及使用事件委托的方式来减少事件监听器的数量。事件委托是一种提高事件处理性能的有效手段,它通过在父元素上监听事件,然后根据事件的目标对象来决定如何处理事件。