【React】面试题5题

news2024/11/23 21:49:48

1. 说说你对 dangerouslySetInnerHTML 的理解

dangerouslySetInnerHTML是React中的一个属性,用于将HTML代码作为字符串直接插入到组件中的DOM元素中。它可以用来动态地生成HTML内容,但同时也带来了一些潜在的安全风险。

使用dangerouslySetInnerHTML时,需要通过一个对象来指定要插入的HTML内容,其中的__html属性值是实际的HTML代码。例如:

<div dangerouslySetInnerHTML={{ __html: '<p>Hello, React!</p>' }}></div>

在使用dangerouslySetInnerHTML时需要注意以下几点来确保安全性:

  1. 避免直接使用用户输入的数据作为dangerouslySetInnerHTML的内容,以防止跨站脚本攻击(XSS)。任何用户提供的内容都应该经过适当的验证和转义,以确保其中没有恶意代码。

  2. 对于动态生成的HTML内容,应该遵循严格的HTML编码规则,确保所有标签和特殊字符都被正确地转义。可以使用第三方库,如React的自带插件react-dom/server中的ReactDOMServer的escape方法,来进行HTML编码。

  3. 尽量避免使用dangerouslySetInnerHTML,而使用React的组件和属性来动态生成DOM和内容。这样可以更好地保持代码的可读性和维护性,也能减少潜在的安全问题。

总的来说,要安全地使用dangerouslySetInnerHTML,需要进行输入验证和HTML编码,尽量避免使用用户输入作为动态内容,并保持警惕性,以防止潜在的安全漏洞。

使用时的消毒dangerouslySetInnerHTML

考虑一下下面的例子,一个JavaScript事件被附加到一个HTML元素上。虽然这些是无害的例子,但它们是概念的证明,表明一个HTML元素如何被利用来运行恶意脚本。

const App = () => {
  const data = `lorem <b οnmοuseοver="alert('mouseover');">ipsum</b>`;

  return (
    <div
      dangerouslySetInnerHTML={{__html: data}}
    />
  );
}

export default App;


const App = () => {
  const data = `lorem ipsum <img src="" οnerrοr="alert('message');" />`;

  return (
    <div
      dangerouslySetInnerHTML={{__html: data}}
    />
  );
}

export default App;

幸运的是,有针对HTML的净化工具,可以检测出HTML代码中潜在的恶意部分,然后输出一个干净安全的版本。最受欢迎的HTML净化工具是DOMPurify。

让我们使用它的在线演示来对上述HTML代码进行消毒,看看它是如何检测并过滤掉代码中可能在执行时产生危险的部分的。

Original
lorem <b onmouseover="alert('mouseover');">ipsum</b>

Sanitized
lorem <b>ipsum</b>
Original
lorem ipsum <img src="" onerror="alert('message');" />

Sanitized
lorem ipsum <img src="">

即使在我们信任数据来源的情况下,使用消毒剂也是很好的做法。在使用DOMPurify包的情况下,上面的一个例子会是这样的。

import DOMPurify from 'dompurify'

const App = () => {
  const data = `lorem <b οnmοuseοver="alert('mouseover');">ipsum</b>`
  const sanitizedData = () => ({
    __html: DOMPurify.sanitize(data)
  })

  return (
    <div
      dangerouslySetInnerHTML={sanitizedData()}
    />
  );
}

export default App;

sanitizedData 函数返回一个带有__html 键的对象,它有一个从DOMPurify.sanitize 函数返回的值。

正如预期的那样,当我们将鼠标悬停在粗体字上时,并没有执行警报函数。

2. setState 是同步,还是异步的?

在React中,setState既可以是同步的,也可以是异步的,具体取决于调用setState的时机和方式。

  1. 异步更新:当在React的事件处理函数(如onClick)或生命周期方法(如componentDidMount)中调用setState时,React会将多个setState调用合并成一个批量更新。这意味着React会等待当前代码块执行完毕,然后一次性更新组件的状态并重新渲染。这样可以提高性能并避免不必要的重复渲染。在异步更新的情况下,无法立即获取到更新后的状态值。

  2. 同步更新:在某些特殊情况下,setState可能会同步更新状态。例如,在setTimeout或原生事件处理函数中直接调用setState,React会立即更新状态并重新渲染组件。在同步更新的情况下,可以立即获取到更新后的状态值。

需要注意的是,无论是同步还是异步更新,React会对多个setState调用进行合并,以减少不必要的更新。这意味着在同一个事件处理函数或生命周期方法中连续多次调用setState,实际上只会触发一次更新。

为了在setState更新完成后执行一些操作,可以使用回调函数作为setState的第二个参数。回调函数会在更新完成并重新渲染组件后被调用。通过回调函数,可以获取到更新后的状态值。

示例代码:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  handleClick = () => {
    this.setState({ count: this.state.count + 1 }, () => {
      console.log("Updated count:", this.state.count);
    });
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.handleClick}>Increment</button>
      </div>
    );
  }
}

在上述代码中,点击按钮会更新count的状态,并在回调函数中打印更新后的count值。这里展示了setState的异步更新行为,以及如何使用回调函数获取更新后的状态值。

错误使用案例:

  const [number, setNumber] = useState(0);

  return (
    <div className="app">
      <button
        onClick={() => {
          setNumber(number + 1);
          console.log("number", number); // 这里永远拿不到最新的number值
        }}
      >
        add
      </button>

onClick事件中,setState是异步的,所以后面console.log中打印的值永远不是最新的值。

3. 我们应该在什么场景下使用 useMemo 和 useCallback ?

useMemo 和 useCallback 是 React 的内置 Hook,通常作为优化性能的手段被使用。他们可以用来缓存函数、组件、变量,以避免两次渲染间的重复计算。但是实践过程中,他们经常被过度使用:担心性能的开发者给每个组件、函数、变量、计算过程都套上了 memo,以至于它们在代码里好像失控了一样,无处不在。

本文希望通过分析 useMemo/useCallback 的目的、方式、成本,以及具体使用场景,帮助开发者正确的决定如何适时的使用他们。赶时间的读者可以直接拉到底部看结论。

我们先从 useMemo/useCallback 的目的说起。

为什么使用 useMemo 和 useCallback

使用 memo 通常有三个原因:

  1. 防止不必要的 effect。
  2. 防止不必要的 re-render。
  3. 防止不必要的重复计算。
    后两种优化往往被误用,导致出现大量的无效优化或冗余优化。下面详细介绍这三个优化方式。

防止不必要的 effect

如果一个值被 useEffect 依赖,那它可能需要被缓存,这样可以避免重复执行 effect。

const Component = () => {
  // 在 re-renders 之间缓存 a 的引用
  const a = useMemo(() => ({ test: 1 }), []);

  useEffect(() => {
    // 只有当 a 的值变化时,这里才会被触发
    doSomething();
  }, [a]);

  // the rest of the code
};

在这段代码中,通过使用useMemo将对象{ test: 1 }缓存起来,确保在组件重新渲染时,a的引用不会发生变化。这样做是为了在依赖项变化时,控制useEffect的执行时机。

在useEffect中,通过将a作为依赖项传递给useEffect的第二个参数,即[a],只有当a的引用发生变化时,即使其他依赖项没有变化,useEffect也会被触发。

如果没有使用useMemo缓存a的引用,每次组件重新渲染时,a的引用都会发生变化,导致useEffect在每次重新渲染时都被触发。

通过使用useMemo缓存a的引用,可以确保只有当a的值实际上发生了变化时,才会触发useEffect。这样可以避免不必要的useEffect调用,提高性能和效率。

需要注意的是,useMemo和useEffect的依赖项是独立的。即使a的引用没有变化,但是useEffect的其他依赖项发生了变化,useEffect也会被触发。因此,在使用useMemo和useEffect时,需要根据具体的业务逻辑和需求,合理定义依赖项,以达到预期的效果。

useCallback 同理:

const Component = () => {
  // 在 re-renders 之间缓存 fetch 函数
  const fetch = useCallback(() => {
    console.log('fetch some data here');
  }, []);

  useEffect(() => {
    // 仅fetch函数的值被改变时,这里才会被触发
    fetch();
  }, [fetch]);

  // the rest of the code

};

当变量直接或者通过依赖链成为 useEffect 的依赖项时,那它可能需要被缓存。这是 useMemo 和 useCallback 最基本的用法。

防止不必要的 re-render

进入重点环节了!!!。正确的阻止 re-render 需要我们明确三个问题:

  1. 组件什么时候会 re-render。
  2. 如何防止子组件 re-render。
  3. 如何判断子组件需要缓存。

1. 组件什么时候会 re-render

三种情况:

  • 当本身的 props 或 state 改变时。
  • Context value 改变时,使用该值的组件会 re-render。
  • 当父组件重新渲染时,它所有的子组件都会 re-render,形成一条 re-render 链。

第三个 re-render 时机经常被开发者忽视,导致代码中存在大量的无效缓存。
例如:

const App = () => {
  const [state, setState] = useState(1);

  const onClick = useCallback(() => {
    console.log('Do something on click');
  }, []);

  return (
	// 无论 onClick 是否被缓存,APP re-render 时 Page 都会 re-render 
    <Page onClick={onClick} />
  );
};

当使用 setState 改变 state 时,App 会 re-render,作为子组件的 Page 也会跟着 re-render。这里 useCallback 是完全无效的,它并不能阻止 Page 的 re-render。

如何防止子组件 re-render?
必须同时缓存 onClick 和组件本身,才能实现 Page 不触发 re-render。

const PageMemoized = React.memo(Page);

const App = () => {
  const [state, setState] = useState(1);

  const onClick = useCallback(() => {
    console.log('Do something on click');
  }, []);

  return (
    // Page 和 onClick 同时 memorize
    <PageMemoized onClick={onClick} />
  );
};

由于使用了React.memo,PageMemoized 会浅比较 props 的变化后再决定是否 re-render。onClick 被缓存后不会再变化,所以 PageMemoized 不再 re-render。

然而,如果 PageMemoized 再添加一个未被缓存的 props,一切就前功尽弃 。。。。 :

const PageMemoized = React.memo(Page);

const App = () => {
  const [state, setState] = useState(1);

  const onClick = useCallback(() => {
    console.log('Do something on click');
  }, []);

  return (
    // page WILL re-render because value is not memoized
    <PageMemoized onClick={onClick} value={[1, 2, 3]} />
  );
};

由于 value 会随着 App 的 re-render 重新定义,引用值发生变化,导致 PageMemoized 仍然会触发 re-render。

现在可以得出结论了,必须同时满足以下两个条件,子组件才不会 re-render:

  1. 子组件自身被缓存。
  2. 子组件所有的 prop 都被缓存。

如何判断子组件需要缓存
我们已经了解,为了防止子组件 re-render,需要以下成本:

  1. 开发者工作量的增加: 一旦使用缓存,就必须保证组件本身以及所有 props 都缓存,后续添加的所有 props 都要缓存。
  2. 代码复杂度和可读性的变化:代码中出现大量缓存函数,这会增加代码复杂度,并降低易读性。
    除此之外还有另外一个成本:性能成本。 组件的缓存是在初始化时进行,虽然每个组件缓存的性能耗费很低,通常不足1ms,但大型程序里成百上千的组件如果同时初始化缓存,成本可能会变得很可观。

所以局部使用 memo,比全局使用显的更优雅、性能更好,坏处是需要开发者主动去判断是否需要缓存该子组件。

🤨 那应该什么时候缓存组件,怎么判断一个组件的渲染是昂贵的?

很遗憾,似乎没有一个简单&无侵入&自动的衡量方式。通常来说有两个方式:

  1. 人肉判断,开发或者测试人员在研发过程中感知到渲染性能问题,并进行判断。
  2. 通过工具,目前有一些工具协助开发者在查看组件性能:
  • 如 React Dev Tools Profiler,这篇文章介绍了使用方式
  • 如这个 hooks:useRenderTimes

另外,React 在 16.5版本后提供了 Profiler API:它可以识别出应用中渲染较慢的部分,或是可以使用类似 memoization 优化的部分。所以可以通过 puppeteer 或 cypress 在自动化集成中测试组件性能,这很适合核心组件的性能测试。

防止不必要的重复计算

如 React 文档所说,useMemo 的基本作用是,避免在每次渲染时都进行高开销的计算。

那什么是“高开销的计算”?

高开销的计算其实极少出现,如下示例,对包含 250 个 item 的数组 countries 进行排序、渲染,并计算耗时。

const List = ({ countries }) => {
  const before = performance.now();
  const sortedCountries = orderBy(countries, 'name', sort);
  // this is the number we're after
  const after = performance.now() - before;

  return (
    // same
  )
};

完整代码:https://codesandbox.io/s/measure-without-memo-tnhggk?file=/src/page.tsx
在这里插入图片描述

结果如图所示,排序耗时仅用了 2.7毫秒,而渲染图中的 List 组件(仅仅只是 button + 文字)却用了 13毫秒,5倍的差距。
大部分情况下,我们的计算量要比这个 250 个 item 的数组少,而组件渲染要比这个 List 组件复杂的多,所以真实程序中,计算和渲染的性能差距会更大。
可见,组件渲染才是性能的瓶颈,应该把 useMemo 用在程序里渲染昂贵的组件上,而不是数值计算上。当然,除非这个计算真的很昂贵,比如阶乘计算。

至于为什么不给所有的组件都使用 useMemo,上文已经解释了。useMemo 是有成本的,它会增加整体程序初始化的耗时,并不适合全局全面使用,它更适合做局部的优化。

为什么 React 没有把缓存组件作为默认配置?

  1. 缓存是有成本的,小的成本可能会累加过高。
  2. 默认缓存无法保证足够的正确性。

结论

讲到这里我们可以总结出 useMemo/useCallback 使用准则了:

  1. 大部分的 useMemo 和 useCallback 都应该移除,他们可能没有带来任何性能上的优化,反而增加了程序首次渲染的负担,并增加程序的复杂性。
  2. 使用 useMemo 和 useCallback 优化子组件 re-render 时,必须同时满足以下条件才有效。
  • 子组件已通过 React.memo 或 useMemo 被缓存
  • 子组件所有的 prop 都被缓存
  1. 不推荐默认给所有组件都使用缓存,大量组件初始化时被缓存,可能导致过多的内存消耗,并影响程序初始化渲染的速度。

4. react是否支持给标签设置自定义的属性,比如给video标签设置webkit-playsinline?

如果你在react中这么样写:

// Your code:
<div mycustomattribute="something" />

在react 15中将被渲染成:

// React 15 output:
<div />

在react 16及之后的版本中将被渲染成:

// React 16 output:
<div mycustomattribute="something" />

但这个会有限制,如果自定义的属性不是 string, number 或者 object,该属性依然会被忽略。

所以目前可以这样添加 webkit-playsinline 属性:

<video webkitPlaysinline={true} controls>
  <source src="video.mp4" type="video/mp4" />
</video>

在上述代码中,webkitPlaysinline被作为video标签的自定义属性,并设置为true。这样可以达到给video标签设置webkit-playsinline的效果。

需要注意的是,设置自定义属性时,React会将驼峰命名法的属性转换为小写和连字符的形式。例如,webkitPlaysinline会被转换为webkit-playsinline。因此,使用驼峰命名法来设置自定义属性时,需要注意属性名的转换规则。

另外,对于一些特殊的属性,如data-*属性或aria-*属性,React会将其保持不变,不进行转换。这样可以方便地设置自定义的数据属性或辅助功能属性。

还可以通过 setAttribute 进行设置,比如:


import * as React from 'react';
import { Component } from 'react';

export class VideoComponent extends Component {
  videoContainer: HTMLDivElement;
  componentDidMount() {
    const video = document.createElement('video');
    video.autoplay = true;
    video.loop = true;
    video.muted = true; // fixes autoplay in chrome
    video.setAttribute('playsinline', 'true'); // fixes autoplay in webkit (ie. mobile safari)

    const source = document.createElement('source');
    source.src = '/path/to/your/video.mp4';
    source.type = 'video/mp4';
    video.appendChild(source);

    this.videoContainer.appendChild(video);
  }
  render() {
    return (
      <div ref={(ref) => { this.videoContainer = ref; }} />
    );
  }
}

5. 说说你对 React Hook的闭包陷阱的理解,有哪些解决方案?

react hooks 一出现便受到了许多开发人员的追捧,或许在使用react hooks 的时候遇到 “闭包陷阱” 是每个开发人员在开发的时候都遇到过的事情,有的两眼懵逼、有的则稳如老狗瞬间就定义到了问题出现在何处。

(以下react示范demo,均为react 16.8.3 版本)

你一定遭遇过以下这个场景:

function App(){
    const [count, setCount] = useState(1);
    useEffect(()=>{
        setInterval(()=>{
            console.log(count)
        }, 1000)
    }, [])
}

在这个定时器里面去打印 count 的值,会发现,不管在这个组件中的其他地方使用 setCount 将 count 设置为任何值,还是设置多少次,打印的都是1。是不是有一种,尽管历经千帆,我记得的还是你当初的模样的感觉? hhh… 接下来,我将尽力的尝试将我理解的,为什么会发生这么个情况说清楚,并且浅谈一些hooks其他的特性。如果有错误,希望各位同学能救救孩子,不要让我带着错误的认知活下去了。。。

1. 一个熟悉的闭包场景

首先从一个各位jser都很熟悉的场景入手。

for ( var i=0; i<5; i++ ) {
    setTimeout(()=>{
        console.log(i)
    }, 0)
}

我就不说为什么最终,打印的都是5的原因了。直接贴出使用闭包打印 0…4的代码:

for ( var i=0; i<5; i++ ) {
   (function(i){
         setTimeout(()=>{
            console.log(i)
        }, 0)
   })(i)
}

这个原理其实就是使用闭包,定时器的回调函数去引用立即执行函数里定义的变量,形成闭包保存了立即执行函数执行时 i 的值,异步定时器的回调函数才如我们想要的打印了顺序的值。

其实,useEffect 的那个场景的原因,跟这个是一样的,useEffect 闭包陷阱场景的出现,是 react 组件更新流程以及 useEffect 的实现的自然而然结果。

2. 浅谈hooks原理,理解useEffect 的 “闭包陷阱” 出现原因。

首先,可能都听过react的 Fiber 架构,其实可以认为一个 Fiber节点就对应的是一个组件。对于 classComponent 而言,有 state 是一件很正常的事情,Fiber对象上有一个 memoizedState 用于存放组件的 state。ok,现在看 hooks 所针对的 FunctionComponnet。 无论开发者怎么折腾,一个对象都只能有一个 state 属性或者 memoizedState 属性,可是,谁知道可爱的开发者们会在 FunctionComponent 里写上多少个 useState,useEffect 等等 ? 所以,react用了链表这种数据结构来存储 FunctionComponent 里面的 hooks。比如

function App(){
    const [count, setCount] = useState(1)
    const [name, setName] = useState('chechengyi')
    useEffect(()=>{
        
    }, [])
    const text = useMemo(()=>{
        return 'ddd'
    }, [])
}

在组件第一次渲染的时候,为每个hooks都创建了一个对象

type Hook = {
  memoizedState: any,
  baseState: any,
  baseUpdate: Update<any, any> | null,
  queue: UpdateQueue<any, any> | null,
  next: Hook | null,
};

最终形成了一个链表。
在这里插入图片描述
这个对象的memoizedState属性就是用来存储组件上一次更新后的 state,next毫无疑问是指向下一个hook对象。在组件更新的过程中,hooks函数执行的顺序是不变的,就可以根据这个链表拿到当前hooks对应的Hook对象,函数式组件就是这样拥有了state的能力。当前,具体的实现肯定比这三言两语复杂很多。

所以,知道为什么不能将hooks写到if else语句中了把?因为这样可能会导致顺序错乱,导致当前hooks拿到的不是自己对应的Hook对象。

useEffect 接收了两个参数,一个回调函数和一个数组。数组里面就是 useEffect 的依赖,当为 [] 的时候,回调函数只会在组件第一次渲染的时候执行一次。如果有依赖其他项,react 会判断其依赖是否改变,如果改变了就会执行回调函数。说回最初的场景:

function App(){
    const [count, setCount] = useState(1);
    useEffect(()=>{
        setInterval(()=>{
            console.log(count)
        }, 1000)
    }, [])
    function click(){ setCount(2) }
}

好,开动脑袋开始想象起来,组件第一次渲染执行 App(),执行 useState 设置了初始状态为1,所以此时的 count 为1。然后执行了 useEffect,回调函数执行,设置了一个定时器每隔 1s 打印一次 count。

接着想象如果 click 函数被触发了,调用 setCount(2) 肯定会触发react的更新,更新到当前组件的时候也是执行 App(),之前说的链表已经形成了哈,此时 useState 将 Hook 对象 上保存的状态置为2, 那么此时 count 也为2了。然后在执行 useEffect 由于依赖数组是一个空的数组,所以此时回调并不会被执行。

ok,这次更新的过程中根本就没有涉及到这个定时器,这个定时器还在坚持的,默默的,每隔1s打印一次 count。 注意这里打印的 count ,是组件第一次渲染的时候 App() 时的 count, count的值为1,因为在定时器的回调函数里面被引用了,形成了闭包一直被保存。

3. 难道真的要在依赖数组里写上的值,才能拿到新鲜的值?

仿佛都习惯性都去认为,只有在依赖数组里写上我们所需要的值,才能在更新的过程中拿到最新鲜的值。那么看一下这个场景:

function App() {
  return <Demo1 />
}

function Demo1(){
  const [num1, setNum1] = useState(1)
  const [num2, setNum2] = useState(10)

  const text = useMemo(()=>{
    return `num1: ${num1} | num2:${num2}`
  }, [num2])

  function handClick(){
    setNum1(2)
    setNum2(20)
  }

  return (
    <div>
      {text}
      <div><button onClick={handClick}>click!</button></div>
    </div>
  )
}

text 是一个 useMemo ,它的依赖数组里面只有num2,没有num1,却同时使用了这两个state。当点击button 的时候,num1和num2的值都改变了。那么,只写明了依赖num2的 text 中能否拿到 num1 最新鲜的值呢?

如果你装了 react 的 eslint 插件,这里也许会提示你错误,因为在text中你使用了 num1 却没有在依赖数组中添加它。 但是执行这段代码会发现,是可以正常拿到num1最新鲜的值的。

如果理解了之前第一点说的“闭包陷阱”问题,肯定也能理解这个问题。

为什么呢,再说一遍,这个依赖数组存在的意义,是react为了判定,在本次更新中,是否需要执行其中的回调函数,这里依赖了的num2,而num2改变了。回调函数自然会执行, 这时形成的闭包引用的就是最新的num1和num2,所以,自然能够拿到新鲜的值。

4. 为什么使用useRef能够每次拿到新鲜的值?

因为初始化的 useRef 执行之后,返回的都是同一个对象。
举个js的例子:

var A = {name: 'chechengyi'}
var B = A
B.name = 'baobao'
console.log(A.name) // baobao

对,这就是这个场景成立的最根本原因。

也就是说,在组件每一次渲染的过程中。 比如 ref = useRef() 所返回的都是同一个对象,每次组件更新所生成的ref指向的都是同一片内存空间, 那么当然能够每次都拿到最新鲜的值了。

所以,提出一个合理的设想。只要我们能保证每次组件更新的时候,useState 返回的是同一个对象的话?我们也能绕开闭包陷阱这个情景吗? 试一下吧。

function App() {
  // return <Demo1 />
  return <Demo2 />
}

function Demo2(){
  const [obj, setObj] = useState({name: 'chechengyi'})

  useEffect(()=>{
    setInterval(()=>{
      console.log(obj)
    }, 2000)
  }, [])
  
  function handClick(){
    setObj((prevState)=> {
      var nowObj = Object.assign(prevState, {
        name: 'baobao',
        age: 24
      })
      console.log(nowObj == prevState)
      return nowObj
    })
  }
  return (
    <div>
      <div>
        <span>name: {obj.name} | age: {obj.age}</span>
        <div><button onClick={handClick}>click!</button></div>
      </div>
    </div>
  )
}

简单说下这段代码,在执行 setObj 的时候,传入的是一个函数。这种用法就不用我多说了把?然后 Object.assign 返回的就是传入的第一个对象。总儿言之,就是在设置的时候返回了同一个对象。

执行这段代码发现,确实点击button后,定时器打印的值也变成了:

{
    name: 'baobao',
    age: 24 
}

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

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

相关文章

函数递归详解

前言&#xff1a; 函数递归是一种算法&#xff0c;递归是通过将问题分解为更小的子问题来解决问题的办法&#xff0c;递归的优点如下&#xff1a; 简洁性&#xff1a;递归可以用较少的代码实现复杂的功能灵活性&#xff1a;递归可以应对未知深度的数据结构&#xff0c;因为它不…

Spring MVC 中的数据绑定和验证机制是什么,如何使用

在 Spring MVC 应用中&#xff0c;数据绑定和验证是非常重要的一部分&#xff0c;它们可以帮助我们将用户提交的数据绑定到 Java 对象上&#xff0c;并对数据进行验证&#xff0c;保证数据的正确性和可靠性。在 Spring MVC 中&#xff0c;数据绑定和验证机制都是通过注解来实现…

Unity 课时 4 : No.4 模拟面试题

课时 4 : No.4 模拟面试题 C# 1. 请说明字符串中 string str null string str “” string str string.Empty 三者的区别 第一个未作初始化没有值, 第二个为空字符串, 答案&#xff1a; str null 在堆中没有分配内存地址 str "" 和 string.Empty 一样都是…

CentOS7 yum安装报错:“Could not resolve host: mirrorlist.centos.org; Unknown error“

虚拟机通过yum安装东西的时候弹出这个错误&#xff1a; 1、查看安装在本机的网卡 网卡ens33处于disconnected的状态 nmcli d2、输入命令&#xff1a; nmtui3、选择网卡&#xff0c;然后点击edit 4、移动到Automatically connect按空格键选择&#xff0c;然后移动到OK键按空格…

Win7 IIS7解析漏洞复现

一、漏洞说明 文件上传使用白名单做限制&#xff0c;只能上传图片文件&#xff0c;导致脚本文件无法上传&#xff0c;上传图片马绕过白名单文件上传的验证&#xff0c;但是图片马又无法解析&#xff0c;利用IIS7.5文件解析漏洞的特点&#xff1a;任意文件名/任意文件名.php&…

华为云云耀云服务器L实例评测 | Linux系统宝塔运维部署H5游戏

文章目录 前言一、云服务器相对传统服务器有什么优势1.1、可伸缩性&#xff08;Scalability&#xff09;1.2、灵活性&#xff08;Flexibility&#xff09;1.3、高可用性&#xff08;High Availability&#xff09;1.4、备份和恢复&#xff08;Backup and Recovery&#xff09;1…

SVN学习笔记--如何 Merge 分支?保姆级教学,带图片手把手实操。

目录 前言实例具体步骤总结 前言 由于项目中有多个分支&#xff0c;如果修改了一处代码&#xff0c;可能需要保证分支和主分支代码一样&#xff0c;所以需要利用 SVN Merge 代码。 实例 现在有两个分支 一个 trunk&#xff1a;主分支一个 develop&#xff1a;开发分支 我们…

数学实验-迭代(Mathematica实现)

一、实验名称&#xff1a;迭代 二、实验环境&#xff1a;Mathematica 10.3软件 三、实验目的&#xff1a;本实验通过Mathematica 10.3软件利用迭代求解方程的近似解&#xff0c;了解迭代方法在解决问题的收敛速度的异同&#xff0c;认识到函数的迭代是数学研究中的一个非常重…

PHPword setImageValue 设置高度不生效

phpword 版本 "phpoffice/phpword": "^0.18.3 我正在使用这个代码&#xff0c;使用模板&#xff0c;写入动态图片&#xff0c;但问题是图像的大小太小&#xff0c;我需要增加高度和宽度 模板文件 如下 问题写法&#xff1a; $file_name "简历";…

UWB学习——day4

UWB学习——day4 技术劣势技术细节UWB频段系统调制方式UWB帧结构芯片实例 技术劣势 干扰其它技术&#xff0c;UWB技术目前允许在未授权的3.1 GHz至10.6 GHz频谱上运行&#xff0c;但该频谱上有许多其它无线通讯所在的频带&#xff0c;容易互相产生干扰&#xff0c;反而限制了适…

基因型数据VCF转EXCEL亲测好用

import pandas as pd df pd.read_csv(shuju.vcf, sep\t, comment#, headerNone,encodingutf-8) df.to_excel(outputFile2.xlsx, indexFalse,encodingutf-8) 以上就是转成功的截图&#xff0c;需要注意的是一定要写入编码方式&#xff0c;UTF-8 &#xff0c;第一次我没有写编码…

实景无人直播系统哪个最好用?呆头鹅无人直播系统

软件图片素材来自于公众号&#xff1a;生财风暴 关注进行领取价值1000元的采集软件&#xff0c;和呆头鹅批量剪辑和矩阵管理系统演示 在未来&#xff0c;想要低成本在人工智能领域创业&#xff0c;其实很简单&#xff0c;如果你是想要低成本创业的人&#xff0c;那么请一定要把…

leetcode 1222. 可以攻击国王的皇后(每日一题)

1222. 可以攻击国王的皇后 在一个 8x8 的棋盘上&#xff0c;放置着若干「黑皇后」和一个「白国王」。 给定一个由整数坐标组成的数组 queens &#xff0c;表示黑皇后的位置&#xff1b;以及一对坐标 king &#xff0c;表示白国王的位置&#xff0c;返回所有可以攻击国王的皇后的…

pcl--第三节 关键点

简介 关键点也称为兴趣点&#xff0c;它是 2D 图像或 3D 点云或曲面模型上,可以通过检测标准来获取的具有稳定性、区别性的点集。从技术上来说,关键点的数量比原始点云或图像的数据量少很多&#xff0c;其与局部特征描述子结合组成关键点描述子。常用来构成原始数据的紧凑表示…

Furion api npm web vue混合开发

Furion api npm web vue混合开发 Furion-api项目获取swagger.json文件复制json制作ts包删除非.ts文件上传到npm获取npm包引用 Furion-api项目获取swagger.json文件 使用所有接口合并的配置文件 复制json制作ts包 https://editor.swagger.io 得到 typescript-axios-clien…

封面人物 | 贾楠:向中介费全面开炮

古人云&#xff0c;燕赵之地多慷慨豪侠之士。贾楠便是一个将豪迈的破局精神融入诸多创意项目的探路者&#xff0c;以及醉心于诗意人生的思考者。 上世纪90年代&#xff0c;他曾尾随南下大军在海南淘得第一桶金。之后&#xff0c;贾楠涉足影视投资&#xff0c;投身健康产业……所…

软件测试如何制作一份亮眼的简历?

简历是入职职场的一张名片&#xff0c;也是进入职场的一块“敲门砖”。从某种角度说&#xff0c;简历也是一张专业人员的说明书。 在互联网行业&#xff0c;如果你在一线企业任职、是业内大佬、技术大牛&#xff0c;基本上大把的高薪工作等你来挑。但是对于转行的小白来说&…

【产品实习评审】对推电影项目核心推荐功能的交互设计比较到位

大家好&#xff0c;本篇文章分享【校招VIP】免费商业项目“推电影”第一期电影详情模块产品同学的原型图周最佳作品。该同学来【莱顿大学】“数学”专业。 1、本项目是基于年轻人的喜好&#xff0c;更个性的电影推荐网站。筛选各分类的知名电影&#xff0c;并给出推荐理由和下…

Python in Visual Studio Code 2023年9月更新

作者&#xff1a;Courtney Webster - Program Manager, Python Extension in Visual Studio Code 排版&#xff1a;Alan Wang 我们很高兴地宣布 Visual Studio Code 的 Python 和 Jupyter 扩展将于 2023 年 9 月发布&#xff01; 此版本包括以下内容&#xff1a; • 将 Python …

2023/9/14 -- C++/QT

作业&#xff1a; 仿照Vector实现MyVector&#xff0c;最主要实现二倍扩容 #include <iostream>using namespace std;template <typename T> class MyVector { private:T *data;size_t size;size_t V_capacity; public://无参构造MyVector():data(nullptr),size(…