2024-08-13

indexOf 方法用于在字符串中查找字符或子字符串,如果找到返回其第一次出现的索引,否则返回 -1

  1. 字符串中查找字符:



let str = "Hello, world!";
let index = str.indexOf("w"); // 返回 7
  1. 字符串中查找子字符串:



let str = "Hello, world!";
let index = str.indexOf("world"); // 返回 7
  1. 字符串中查找字符(从指定位置开始):



let str = "Hello, world!";
let index = str.indexOf("w", 8); // 返回 11
  1. 数组中查找元素:



let arr = [1, 2, 3, 4, 5];
let index = arr.indexOf(3); // 返回 2
  1. 数组中查找元素(从指定位置开始):



let arr = [1, 2, 3, 4, 5];
let index = arr.indexOf(3, 2); // 返回 2
  1. 数组中查找不存在的元素:



let arr = [1, 2, 3, 4, 5];
let index = arr.indexOf(6); // 返回 -1

indexOf 方法对大小写敏感。如果需要不区分大小写的搜索,可以使用 toLowerCase()toUpperCase() 方法先转换字符串。

2024-08-13

题目描述:

在一个社区里有 n 个人,编号为 1 到 n。每个人都有一个特定的健康状态,其中 health[i] 表示编号为 i 的人的健康状态。

每天,每个人都会选择一个编号在 [1, n] 的人与他/她交流。如果两个人交流的次数超过所有其他人的交流次数之和,那么他们就会被确定为“传染者”。

给你一个整数 n 和一个数组 health 。返回使得至少一个人成为“传染者”的最小交流次数。

示例 1:

输入:n = 4, health = [1,1,1,1]

输出:0

解释:无需任何交流,所有人的健康状态都是 1。

示例 2:

输入:n = 2, health = [1,2]

输出:1

解释:需要 1 次交流,编号为 1 和 2 的人进行交流,健康状态变为 [0,0],就都成为了“传染者”。

示例 3:

输入:n = 4, health = [1,2,3,4]

输出:2

解释:需要 2 次交流,编号为 1 和 2 的人进行 1 次交流,编号为 3 和 4 的人进行 1 次交流,使得健康状态变为 [0,0,0,0]。

提示:

  • 1 <= n <= 10^5
  • health.length == n
  • 1 <= health[i] <= n

解题思路:

这是一个求最小值的问题,可以通过二分查找来实现。首先,我们需要定义一个函数,该函数接收交流次数作为参数,然后检查是否至少有一个人在交流后成为“传染者”。

解决方案:

Java、Python、C、C++ 的代码实现略有不同,但核心思路相同。以下是使用二分查找实现的 Python 代码:




class Solution:
    def minSessions(self, n: int, health: List[int]) -> int:
        def isPossible(x):
            cnt = [0] * n
            for h in health:
                cnt[h - 1] += 1
            for i in range(n):
                if cnt[i] > x:
                    return False
                if cnt[i] == x:
                    cnt[(i + 1) % n] -= 1
            return True
 
        left, right = 0, n * (n - 1) // 2
        while left <= right:
            mid = (left + right) // 2
            if isPossible(mid):
                right = mid - 1
            else:
                left = mid + 1
        return left

注意:

  • 该解决方案假设交流是双向的,即编号为 i 和 j 的人交流后,编号为 i 和 j 的健康状态都减 1,并且编号为 i+1 和 j+1 的健康状态也减 1。
  • 该解决方案使用二分查找来减少时间复杂度,但仍然可能超时,因为时间复杂度为 O(n log(max\_health))。如果需要通过所有测试用例,可能需要优化算法。
2024-08-12

在JavaScript中实现水印功能,并防止用户去除水印,可以通过以下三种方法:

  1. 使用Canvas绘制水印
  2. 使用CSS属性为元素添加背景图片
  3. 使用HTML属性contenteditable创建可编辑区域

方法1:使用Canvas绘制水印




function createWatermark(text) {
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    canvas.width = 300;
    canvas.height = 200;
    ctx.font = '20px Arial';
    ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';
    ctx.rotate(-20 * Math.PI / 180);
    ctx.fillText(text, -100, 150);
 
    return canvas;
}
 
document.body.style.backgroundImage = 'url(' + createWatermark('Watermark').toDataURL('image/png') + ')';

方法2:使用CSS属性为元素添加背景图片




.watermark {
    background-image: url('watermark.png');
    background-repeat: repeat;
    background-position: center;
}



document.body.classList.add('watermark');

方法3:使用HTML属性contenteditable创建可编辑区域




<div contenteditable="true">
    这是一个可编辑的区域,但不能去除水印。
</div>

在这些方法中,Canvas和CSS方法可以生成图片作为水印,而contenteditable属性则创建了一个可以接受输入但不容易被删除的区域。但是,请注意,任何客户端的JavaScript水印都不能完全防止用户去除,因为最终还是需要依赖于客户端的环境。

2024-08-12



import * as THREE from 'three';
import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
 
let scene, camera, renderer, labelRenderer, mesh;
 
function init() {
    scene = new THREE.Scene();
 
    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
    camera.position.z = 1;
 
    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
 
    // 创建CSS2DRenderer
    labelRenderer = new CSS2DRenderer();
    labelRenderer.setSize(window.innerWidth, window.innerHeight);
    labelRenderer.domElement.style.position = 'absolute';
    labelRenderer.domElement.style.top = 0;
    document.body.appendChild(labelRenderer.domElement);
 
    // 创建3D对象
    let geometry = new THREE.PlaneGeometry(0.5, 0.5);
    let material = new THREE.MeshBasicMaterial({ color: 0x00ff00, transparent: true });
    mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);
 
    // 创建CSS2DObject
    let label = document.createElement('div');
    label.style.color = 'red';
    label.textContent = 'Hello, CSS2D!\n3D object!';
    let labelObject = new CSS2DObject(label);
    labelObject.position.set(0, 0, 0);
    scene.add(labelObject);
 
    // 监听窗口大小变化
    window.addEventListener('resize', onWindowResize, false);
 
    animate();
}
 
function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
 
    renderer.setSize(window.innerWidth, window.innerHeight);
    labelRenderer.setSize(window.innerWidth, window.innerHeight);
}
 
function animate() {
    requestAnimationFrame(animate);
 
    renderer.render(scene, camera);
    labelRenderer.render(scene, camera);
}
 
init();

这段代码初始化了Three.js场景,并使用CSS2DRenderer渲染了一个2D标签,它会随着3D对象一起旋转。这个例子简单地展示了如何将HTML元素与3D场景中的对象相关联,这在创建交互式数据可视化时非常有用。

2024-08-12



// 主线程文件 main.js
// 创建并使用 Web Worker
 
// 检查浏览器是否支持 Web Worker
if (typeof Worker !== 'undefined') {
  // 创建一个新的 Web Worker
  const worker = new Worker('worker.js'); // 'worker.js' 是 Web Worker 脚本文件
 
  // 向 Web Worker 发送数据
  worker.postMessage({ msg: 'Hello, Web Worker!' });
 
  // 接收 Web Worker 发送回来的数据
  worker.onmessage = function(event) {
    console.log('Received message from worker:', event.data);
  };
 
  // 监听 Web Worker 的错误
  worker.onerror = function(error) {
    console.error('Error from worker:', error);
  };
 
  // 当 Web Worker 处理完毕后,会自动关闭。
  // 如果需要提前关闭 Web Worker,可以使用 worker.terminate() 方法。
} else {
  console.log('Your browser doesn\'t support Web Workers.');
}



// Web Worker 文件 worker.js
// 这是 Web Worker 的代码,它在一个单独的线程中运行
 
// 处理消息
onmessage = function(event) {
  // 在这里处理接收到的消息
  console.log('Message from main script:', event.data.msg);
 
  // 执行一些计算任务...
 
  // 发送消息回主线程
  postMessage({ result: 'Processed data in Web Worker' });
};
 
// 当 Web Worker 处理完毕后,会自动关闭。
// 如果需要提前关闭 Web Worker,可以在主线程使用 worker.terminate() 方法。

以上代码演示了如何在主线程中创建并使用一个 Web Worker。主线程发送消息给 Worker,Worker 处理完毕后再将结果发送回主线程。这样可以在不阻塞用户界面的前提下执行耗时任务。

2024-08-12

在JavaScript中实现任意位置缩放图片,通常涉及到事件监听和计算。以下是一个简单的实现示例:

HTML部分:




<img id="image" src="path/to/your/image.jpg" alt="Resizable Image" />
<div id="handles">
  <div class="handle e">e</div>
  <div class="handle s">s</div>
  <div class="handle w">w</div>
  <div class="handle n">n</div>
  <div class="handle ne">ne</div>
  <div class="handle se">se</div>
  <div class="handle sw">sw</div>
  <div class="handle nw">nw</div>
</div>

CSS部分:




#image {
  position: absolute;
  cursor: move;
}
#handles {
  position: absolute;
  z-index: 10;
}
.handle {
  position: absolute;
  width: 10px;
  height: 10px;
  background: #ccc;
  font-size: 12px;
  color: #fff;
  line-height: 10px;
  text-align: center;
  cursor: nwse-resize;
  z-index: 100;
}
/* Define the positions of the resize handles */
.handle.e { top: 0; right: 0; }
.handle.s { bottom: 0; right: 0; }
.handle.w { top: 0; left: 0; }
.handle.n { top: 0; left: 0; }
.handle.ne { top: 0; right: 0; }
.handle.se { bottom: 0; right: 0; }
.handle.sw { bottom: 0; left: 0; }
.handle.nw { top: 0; left: 0; }

JavaScript部分:




const image = document.getElementById('image');
const handles = document.querySelectorAll('#handles .handle');
let isResizing = false;
let startX, startY, startWidth, startHeight;
 
handles.forEach(handle => {
  handle.addEventListener('mousedown', function(e) {
    e.preventDefault();
    isResizing = true;
 
    startX = e.clientX;
    startY = e.clientY;
    startWidth = parseInt(image.width, 10);
    startHeight = parseInt(image.height, 10);
 
    document.addEventListener('mousemove', resize);
    document.addEventListener('mouseup', stopResize);
  });
});
 
function resize(e) {
  if (isResizing) {
    const deltaX = e.clientX - startX;
    const deltaY = e.clientY - startY;
 
    // Resize according to the handle position
    switch (this.className) {
      case 'handle e':
        image.width = startWidth + deltaX;
        break;
      case 'handle s':
        image.height = startHeight + deltaY;
        break;
      case 'handle w':
        image.width = startWidth - deltaX;
        image.style.left = s
2024-08-12

解释:

ReferenceError: Symbol is not defined 表示在 Node.js 环境中引用了 Symbol 这个全局对象,但是当前的执行环境中并没有定义这个对象。通常这种错误出现在 Node.js 的较旧版本中,旧版本的 JavaScript 标准中不包括 Symbol 这种新的数据类型。

解决方法:

  1. 升级 Node.js 到一个支持 Symbol 的版本。可以通过 Node.js 官方网站下载最新稳定版本。
  2. 如果你不能升级 Node.js 版本,可以考虑使用 core-js 或者 babel 这样的库来提供对新 JavaScript 特性的支持。
  3. 如果你的代码是在较新的环境中编写的,但需要在旧版本的 Node.js 中运行,确保在旧版本中引入了必要的 polyfill。

示例使用 core-js 的方法:

  1. 安装 core-js

    
    
    
    npm install core-js
  2. 在代码的入口文件中引入 core-jses6 模块,以确保 Symbol 等新特性被加载:

    
    
    
    require('core-js/es6');
    // 你的其他代码

确保在不支持 Symbol 的 Node.js 版本中,你的代码有适当的 polyfill 或者转译工具来模拟这些特性。

2024-08-12



import { useState } from 'react';
import Link from 'next/link';
import { useRouter }s next/router';
 
// 假设我们有一个API客户端来处理HTTP请求
import { apiClient } from '../../lib/api-client';
 
export default function PostsPage({ posts }) {
  const router = useRouter();
  const [isLoading, setIsLoading] = useState(false);
 
  const handleDelete = async (id) => {
    if (window.confirm('Are you sure you want to delete this post?')) {
      setIsLoading(true);
      try {
        await apiClient.delete(`/posts/${id}`);
        router.replace(router.asPath);
      } catch (error) {
        alert('Failed to delete post');
      } finally {
        setIsLoading(false);
      }
    }
  };
 
  return (
    <div>
      <h1>Posts</h1>
      <p>
        <Link href="/posts/new">
          <a>New Post</a>
        </Link>
      </p>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>
            <Link href={`/posts/${post.id}`}>
              <a>{post.title}</a>
            </Link>
            <button onClick={() => handleDelete(post.id)} disabled={isLoading}>
              {isLoading ? 'Deleting...' : 'Delete'}
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}
 
// 在页面加载时获取帖子
export async function getServerSideProps() {
  try {
    const { data: posts } = await apiClient.get('/posts');
    return { props: { posts } };
  } catch (error) {
    return { props: { posts: [] } };
  }
}

这个代码示例展示了如何使用Next.js 13创建一个简单的CRUD API应用。它使用了客户端路由,以及在服务器端获取初始数据。注意,示例中的apiClient是假设存在的,需要在项目中实现相应的API客户端逻辑。

2024-08-12



// 方法1: 使用toISOString()并进行字符串替换
let date1 = new Date().toISOString().slice(0, 19).replace('T', ' ');
console.log(date1);
 
// 方法2: 使用Date.prototype.getTimezoneOffset()修正时间
let date2 = new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60000);
console.log(date2.toISOString().slice(0, 19).replace('T', ' '));
 
// 方法3: 使用moment.js库
let date3 = moment().format('YYYYMMDDHHmmss');
console.log(date3);
 
// 方法4: 使用Date.prototype.toLocaleString()
let date4 = new Date().toLocaleString('zh-CN', { hour12: false }).replace(/\D/g, '');
console.log(date4);
 
// 方法5: 使用Date.prototype.getFullYear()等方法手动构建
let date5 = new Date();
let year = date5.getFullYear();
let month = (date5.getMonth() + 1).toString().padStart(2, '0');
let day = date5.getDate().toString().padStart(2, '0');
let hour = date5.getHours().toString().padStart(2, '0');
let minute = date5.getMinutes().toString().padStart(2, '0');
let second = date5.getSeconds().toString().padStart(2, '0');
let date6 = `${year}${month}${day}${hour}${minute}${second}`;
console.log(date6);
 
// 方法6: 使用Function.prototype.call()和Date.prototype.getTime()
let date7 = Function.prototype.call.bind(Date.prototype.getTime)({ getTime: Date.prototype.getTime }).call() / 1000 | 0;
console.log(date7.toString().padStart(14, '0'));

每种方法都有其特点,可以根据实际需求选择合适的方法。

2024-08-12

防抖(debounce)和节流(throttle)是前端开发中常用的性能优化手段,用以控制函数执行的频率,以减少计算资源的使用。

防抖:指的是在一定时间内,若函数被连续调用,则会把前面的调用忽略,只执行最后一次。

节流:指的是在一定时间内,无论函数被调用多少次,都只在指定的时间间隔内执行一次。

以下是实现防抖和节流的示例代码:

防抖:




function debounce(fn, wait) {
    let timeout = null;
    return function() {
        let context = this;
        let args = arguments;
        if (timeout) clearTimeout(timeout);
        let callNow = !timeout;
        timeout = setTimeout(() => {
            timeout = null;
        }, wait);
        if (callNow) fn.apply(context, args);
    };
}
 
// 使用
let myFunc = debounce(function() {
    console.log('防抖函数被调用');
}, 200);
window.addEventListener('resize', myFunc);

节流:




function throttle(fn, wait) {
    let previous = 0;
    return function() {
        let context = this;
        let args = arguments;
        let now = new Date();
        if (now - previous > wait) {
            fn.apply(context, args);
            previous = now;
        }
    };
}
 
// 使用
let myFunc = throttle(function() {
    console.log('节流函数被调用');
}, 200);
window.addEventListener('mousemove', myFunc);