慕课前端售1299元的面试题【第二阶段】汇总 day05

上一篇链接

如果有看不懂的,别硬看,直接chatgpt,让它回答。

- 我的博客需要缩宽页面观看,图片无法均放,很抱歉。

1. 请说明 Ajax Fetch Axios 三者的区别?

在这里插入图片描述

在这里插入图片描述
1. 用 XMLHttpRequest 实现 Ajax

 function ajax1(url, successFn) {
    
    
    const xhr = new XMLHttpRequest()
    xhr.open("GET", url, false)
    xhr.onreadystatechange = function () {
    
    
      // 这里的函数异步执行
      if (xhr.readyState == 4) {
    
    
        if (xhr.status == 200) {
    
    
          successFn(xhr.responseText)
        }
      }
    }
    xhr.send(null)
  }

在这里插入图片描述
2.使用Fetch发送POST请求提交数据:

fetch('/api/data', {
    
    
  method: 'POST',
  body: JSON.stringify({
    
     name: 'John', age: 30 }),
  headers: {
    
    
    'Content-Type': 'application/json'
  }
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));

3.使用Axios发送PUT请求更新数据:

axios.put('/api/data/123', {
    
     name: 'Jane', age: 35 })
  .then(response => console.log(response.data))
  .catch(error => console.error(error));
  • 使用原生的Ajax需要手动创建XMLHttpRequest对象,并编写回调函数来处理响应。
  • Fetch则更加现代化,使用Promise封装了网络请求,并提供了更简洁的API。
  • 而Axios则在Fetch的基础上进一步封装,提供了更多的选项和错误处理机制。

lib 和 API的区别? 直接问chatgpt ,它回答全面

2. px % em rem vw vh 有什么区别?

  • px(基本单位,绝对单位):它指定了物体在屏幕上的精确尺寸,例如1个像素就是指视觉上的最小点。这意味着,如果在不同的设备上使用相同数量的像素,那么它们在不同的屏幕上看起来可能会有不同的大小,在高分辨率的屏幕上可能会显示更细致的细节。

  • 百分比(%)是相对单位,它是相对于父元素的大小来计算的。例如,如果一个元素的宽度设置为50%,那么它将占据其父元素宽度的50%。这使得百分比非常适合用于响应式设计,因为它可以自动调整大小以适应不同屏幕大小的父容器。

  • em(字体相对长度单位):em是基于当前元素的字体大小来计算其他元素的大小的相对单位。例如,如果一个元素的字体大小为16px,那么1em就等于16px。如果另一个元素的字体大小为20px,那么1em就等于20px。

  • rem(根元素字体大小单位):rem也是相对单位,但是它是相对于根元素的字体大小来计算其他元素的大小的。根元素通常是HTML元素。

  • vw(视窗宽度单位):vw是相对于视口宽度的单位。1vw等于视口宽度的1%,例如,如果视口宽度为1000像素,那么1vw就等于10像素。

  • vh(视口高度单位):vh是相对于视口高度的单位。1vh等于视口高度的1%。

3. 箭头函数的缺点?

在这里插入图片描述

  • 箭头函数无法通过call()、apply()和bind()方法来改变其this值。因此,如果你需要在函数内部访问不同的this值,就不能使用箭头函数。
  • 箭头函数没有自己的arguments对象。在箭头函数中访问arguments将会引用外层函数的arguments对象,这可能导致意想不到的结果。
  • 箭头函数不能用作构造函数,因为它们没有自己的this值。

4. 什么时候不可以使用箭头函数?

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5. 请描述 TPC 三次握手和四次挥手

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6. 防抖和节流

<!DOCTYPE html>
<html>
<head>
  <title>防抖函数输入框</title>
  <script>
    // 定义防抖函数 debounce,用于延迟执行某个函数。
    function debounce(fn, delay) {
      
      
      // 创建一个变量 timerId 并初始化为 null。
      let timerId = null;
      // 返回一个无名函数,它使用剩余参数语法来获取任意数量的参数,并在内部实现防抖逻辑。
      return function debounced(...args) {
      
      
        // 如果 timerId 不是 null,则调用 clearTimeout 方法取消先前的计时器。
        if (timerId !== null) {
      
      
          clearTimeout(timerId);
        }
        // 创建一个新的计时器并将其 ID 存储在 timerId 中。该计时器将在 delay 毫秒后执行一个匿名函数。
        timerId = setTimeout(() => {
      
      
          // :在计时器触发时执行原始函数 fn,并将 this 上下文设置为当前作用域。
          fn.apply(this, args);
          // 重置 timerId 变量以便可以创建新的计时器。
          timerId = null;
        }, delay);
      };
    };
    // 在页面加载完成后执行以下函数
    window.onload = function () {
      
      
      // 获取 ID 为 myInput 的输入框元素
      const input = document.getElementById('myInput');
      // 处理输入事件的回调函数
      function handleInput() {
      
      
        console.log(input.value);
      }
      // 创建防抖函数
      const debouncedHandleInput = debounce(handleInput, 300);
      // 将防抖函数绑定到输入框的输入事件上
      input.addEventListener('input', debouncedHandleInput);
    }
  </script>
</head>
<body>
  <input type="text" id="myInput">
</body>
</html>

7. for in 和 for of 有什么区别?

请添加图片描述
请添加图片描述
在这里插入图片描述

8. for await …of 有什么作用?

  • for await…of 是用于异步迭代器的语法。异步迭代器是一种特殊类型的迭代器,它支持异步操作并返回 Promise 对象。

  • 在传统的同步迭代中,我们可以使用 for…of 循环来遍历一个可迭代对象,例如数组或字符串。但对于异步操作,我们需要等待 Promise 对象解决之后才能继续执行下一步操作,因此需要使用 await 关键字。而 for await…of 语法正是为了简化这一过程而设计的。

function createPromise(val) {
    
    
      return new Promise((resolve) => {
    
    
        setTimeout(() => {
    
    
          resolve(val)
        }, 1000)
      })
    }
    (async function () {
    
    
      const p1 = createPromise(100)
      const p2 = createPromise(200)
      const p3 = createPromise(300)

      const list = [p1, p2, p3]
      // 一秒后,100,200,300 一次性展示出来
      // Promise.all(list).then(res => console.log(res))

      // Promise.all是api形式 , for await ...of是循环形式

      // for await ...of 就是 Promise.all一个代替品
      for await (let res of list) {
    
    
        console.log(res);// 一秒后,100,200,300 一次性展示出来
      }
    })()
  <script>
    function createPromise(val) {
    
    
      return new Promise((resolve) => {
    
    
        setTimeout(() => {
    
    
          resolve(val)
        }, 1000)
      })
    }
    (async function () {
    
    
      const res1 = await createPromise(100)
      console.log(res1);
      const res2 = await createPromise(200)
      console.log(res2);
      const res3 = await createPromise(300)
      console.log(res3);
      // 依次打印 100 200 300

      const arr = [10, 20, 30]
      for await (let num of arr) {
    
    
        const res = await createPromise(num)
        console.log(res);
      } // 依次打印 10 20 30
    })()
  </script>

9. offsetHeight 、clientHeight、 ScrollHeight 有什么区别?

offsetHeight, clientHeight, and scrollHeight是用于获取元素高度的三个不同属性。

  • offsetHeight属性返回一个元素在垂直方向上占用的空间大小,包括该元素的高度、(可见的)水平滚动条的高度、上下边框的高度。它包含了该元素在屏幕上所占的所有空间,即使这些空间是不可见的或被滚动条遮挡着的。

  • clientHeight 属性返回的是一个元素内部的高度,包括该元素的内边距(padding)的高度,但不包括水平滚动条、边框(border)和外边距(margin)。

  • scrollHeight 属性返回的是元素的内容高度,包括那些因为溢出导致显示不出来的部分。如果元素没有溢出,则scrollHeight会等于clientHeight。

需要注意的是,clientHeight和scrollHeight的值都可以受到CSS样式的影响。例如,如果一个元素的overflow属性设置为hidden,则其scrollHeight将小于clientHeight,因为部分内容被隐藏了。
在这里插入图片描述

10. HTMLCollection 和 NodeList 区别?

在这里插入图片描述
在这里插入图片描述

11. vue中 computed 和 watch 的区别?

  • 在Vue中,计算属性(computed)和侦听属性(watch)都是用于监控数据变化的。

  • 计算属性是基于它们的依赖进行缓存的。只有当一个计算属性的相关依赖发生改变时,才会重新求值。这样可以避免不必要的计算,提高应用程序的性能。计算属性通常用于派生出一些需要动态计算的值。

例如:

data: {
    
    
  firstName: 'John',
  lastName: 'Doe'
},
computed: {
    
    
  fullName: function () {
    
    
    return this.firstName + ' ' + this.lastName
  }
}

在这个例子中,fullName 是一个计算属性,它依赖于 firstName 和 lastName 这两个属性。每当这两个属性中的任何一个发生变化时,fullName 都将被重新计算。

  • 侦听属性是用于监测某个属性的变化并执行相应的操作。当需要在数据变化时执行异步或开销较大的操作时,使用侦听属性比计算属性更合适。

例如:

data: {
    
    
  message: 'Hello, Vue.js!'
},
watch: {
    
    
  message: function (newMessage, oldMessage) {
    
    
    console.log('New message: ', newMessage, ' Old message: ', oldMessage)
  }
}

在这个例子中,message 是一个数据属性,watch 监听 message 的变化,并在 message 发生变化时执行回调函数。

综上所述,计算属性和侦听属性都是用于监控数据的变化,但它们有不同的应用场景。计算属性适合派生出需要动态计算的值,而侦听属性适合在数据变化时执行异步或开销较大的操作。

12. vue2组件通讯方式有哪些?分别举例说明?

  • 在 Vue2 中,组件之间有以下几种通信方式:
  1. PropsEvents:父组件通过 props 向子组件传递数据,子组件通过 events 向父组件发送消息。
    适用于父子组件通讯

例如,父组件向子组件传递一个名字:

<template>
  <child-component :name="parentName" @send-msg="handleChildMsg"></child-component>
</template>

<script>
export default {
      
      
  data() {
      
      
    return {
      
      
      parentName: 'John'
    }
  },
  methods: {
      
      
    handleChildMsg(msg) {
      
      
      console.log('接收子组件的信息', msg)
    }
  }
}
</script>
  • 在子组件中接收 name 属性,并且当按钮被点击时,通过 emit 发送消息给父组件:
<template>
  <div>
    <p>Hello, {
   
   { name }}!</p>
    <button @click="sendMessage">Send Message</button>
  </div>
</template>

<script>
export default {
      
      
  props: ['name'],
  methods: {
      
      
    sendMessage() {
      
      
      this.$emit('send-msg', 'Hello from child!')
    }
  }
}
</script>
  1. 通过 $ emit 和 on:非父子组件之间的通信可以使用事件总线来实现。
    利用Vue实例作为事件中心,emit 触发事件,$on 监听事件,并执行回调函数。
    适用于两个不相干的组件通讯

让我们创建一个名为EventBus.js的新文件,并在其中导入Vue并创建新的Vue实例作为事件总线:

import Vue from 'vue';
export const EventBus = new Vue();

例如,在一个页面中,有两个组件需要进行通信:

<template>
  <div>
    <first-component></first-component>
    <second-component></second-component>
  </div>
</template>

<script>
import EventBus from './event-bus'

export default {
      
      
  methods: {
      
      
    handleEvent(msg) {
      
      
      console.log('received message:', msg)
    }
  },
  mounted() {
      
      
    EventBus.$on('send-msg', this.handleEvent)
  },
  beforeDestroy() {
      
      
    EventBus.$off('send-msg', this.handleEvent);
  }
}
</script>

在 first-component 组件中,通过 $emit 发送消息:

<template>
  <div>
    <button @click="sendMessage">Send Message</button>
  </div>
</template>

<script>
import EventBus from './event-bus'

export default {
      
      
  methods: {
      
      
    sendMessage() {
      
      
      EventBus.$emit('send-msg', 'Hello from first component!')
    }
  }
}
</script>

在 second-component 中同样可以通过 $emit 发送消息。

  1. Vuex:Vuex 是一个专门为 Vue.js 应用程序开发的状态管理模式。通过 store 对象来实现组件之间的通信。

例如,在一个购物车应用中,多个组件需要共享购物车状态:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
    
    
  state: {
    
    
    cart: []
  },
  mutations: {
    
    
    addToCart(state, product) {
    
    
      state.cart.push(product)
    }
  }
})

export default store

在组件中使用 $store 来访问 store 对象:

<template>
  <div>
    <button @click="addToCart">Add to Cart</button>
  </div>
</template>

<script>
export default {
    
    
  methods: {
    
    
    addToCart() {
    
    
      this.$store.commit('addToCart', {
    
     name: 'Product A', price: 100 })
    }
  }
}
</script>

通过在其他组件中也使用 $store 来访问 store 对象,就可以实现共享状态。

13. vue3通讯方式,如下。

1. 在Vue 3中,我们可以使用 event-emitter库

来实现自定义事件的发布和订阅,实现组件之间的通信。

  • 下面是一个简单的示例:
// eventBus.js
import ee from 'event-emitter'

const event = ee()

export default event
<template>
  <div>
    <h2>Parent Component</h2>
    <button @click="emitCustomEvent">发出自定义事件</button>
    <child-component />
  </div>
</template>

<script>
import {
    
     reactive } from 'vue'
import {
    
     emitter } from '../eventBus'
import ChildComponent from './ChildComponent.vue'

export default {
    
    
  components: {
    
     // 注册组件
    ChildComponent,
  },
  setup() {
    
    
    const state = reactive({
    
    
      message: 'Hello from Parent',
    })

    const emitCustomEvent = () => {
    
    
      emitter.emit('custom-event', {
    
     data: '自定义事件数据' })
    }

    return {
    
    
      state,
      emitCustomEvent,
    }
  },
}
</script>

在这个示例中,我们首先导入了一个名为emitter的EventEmitter实例,并将其用于发布自定义事件。接下来,在父组件的setup()函数中,我们创建了一个响应式对象state,并定义了一个 emitCustomEvent()方法,在该方法中使用emitter.emit()方法触发了一个名为custom-event的自定义事件,并且传递了一个包含数据的对象。

接下来,我们创建了一个子组件,并在子组件中监听了这个自定义事件:

<template>
  <div>
    <h2>Child Component</h2>
    <p>{
    
    {
    
     message }}</p>
  </div>
</template>

<script>
import {
    
     reactive, onMounted ,onBeforeUnmount} from 'vue'
import {
    
     emitter } from '../eventBus'

export default {
    
    
  setup() {
    
    
    const state = reactive({
    
    
      message: '',
    })

    const handleCustomEvent = (data) => {
    
    
      console.log('接收数据 in child:', data)
      state.message = data.data
    }

    onMounted(() => {
    
    
      emitter.on('custom-event', handleCustomEvent)
    })
    onBeforeUnmount(() => {
    
    
      emitter.off('custom-event', handleCustomEvent)
    })
    return {
    
    
      state,
    }
  },
}
</script>

在子组件的setup()函数中,我们定义了一个响应式对象state,并且在子组件挂载时使用emitter.on()方法监听了custom-event自定义事件,并在该事件被触发时调用了一个名为handleCustomEvent()的方法。在这个方法中,我们首先打印了传递过来的数据,并将数据设置到了state.message属性上。

2. 使用 $attrs传递数据

在 Vue 3 中,可以通过 $attrs 属性将父组件中未声明为 props 的属性传递给子组件
$attrs是 props 和 emits 的后补

Level1组件如下:

<template>
  <p>Level1</p>
  <Level2 :a="a" :b="b" :c="c" @getA="getA" @getB="getB" @getC="getC"></Level2>
</template>
<script>
  import Level2 from './Level2'
  export default {
    
    
    name: 'Level1',
    components: {
    
     Level2 },
    data() {
    
    
      return {
    
    
        a: 'aaa',
        b: 'bbb',
        c: 'ccc'
      }
    },
    methods: {
    
    
      getA() {
    
    
        return this.a
      },
      getB() {
    
    
        return this.b
      },
      getC() {
    
    
        return this.c
      }
    }
  }
</script>

Level2组件如下:

<template>
  <p>Level2</p>
  <Level3 :x="x" :y="y" :z="z" @getX="getX" @getY="getY" @getZ="getZ" v-bind="$attrs"></Level3>
</template>
<script>
  import Level3 from './Level3'
  export default {
    
    
    name: 'Level2',
    components: {
    
     Level3 },
    props: ['a'],
    emits: ['getA'],
    data() {
    
    
      return {
    
    
        x: 'xxx',
        y: 'yyy',
        z: 'zzz'
      }
    },
    methods: {
    
    
      getX() {
    
    
        return this.x
      },
      getY() {
    
    
        return this.y
      },
      getZ() {
    
    
        return this.z
      }
    },
    created() {
    
    
      console.log(Object.keys(this.$attrs));
    }
  }
</script>

这里使用了 inheritAttrs: false 将默认行为禁用掉,因此只有在 props 中定义的属性才会被接收。

如果你想要将 $attrs 中的所有属性都显式地声明为 props,可以使用 v-bind=" $attrs " 将其传递给子组件。
Level3组件如下:

<template>
  <p>Level3</p>
</template>
<script>
  export default {
    
    
    name: 'Level3',
    props: ['x'],
    emits: ['getX'],
    inheritAttrs: false,
    data() {
    
    
      return {
    
    
      }
    },
    created() {
    
    
      console.log('level3', Object.keys(this.$attrs));
    },
    mounted(){
    
    
       console.log(this.$parent.getX())
    }
  }
</script>

this.$parent.getX() 可以直接获取Level2中的getX() 方法,也就是 $parent可以获取父组件的方法,控制台输出xxx。
在这里插入图片描述

  • 可以通过 $parent获取父组件,可以通过 $refs获取子组件
<template>
  <div>
    <child-component ref="child"></child-component>
    <button @click="handleClick">调用子组件方法</button>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
    
    
  components: {
    
    
    ChildComponent,
  },
  methods: {
    
    
    handleClick() {
    
    
      this.$refs.child.sayHello();
    }
  }
}
</script>

当使用$refs时,我们需要在子组件上添加ref属性,该属性的值应与我们在父组件中定义的引用名相同。因此,在子组件模板中,我们可以这样添加ref属性:

<template>
  <div ref="child">
    <!-- 子组件内容 -->
  </div>
</template>

<script>
export default {
    
    
  methods: {
    
    
    sayHello() {
    
    
      console.log('Hello from child component!');
    }
  }
}
</script>

3. provide和inject是一对用于跨组件传递数据的API。

  • provide定义了一个对象,其中包含要传递给子组件的属性或方法。inject可以在子组件中接收这些属性或方法。

  • 使用provide和inject可以避免使用全局事件总线或Vuex等状态管理库来共享数据。它还可以更方便地将数据从父组件传递给多个嵌套子组件。

看以下案例
在父组件中,例如App.vue,你可以像这样使用provide:

provide() {
    
    
  return {
    
    
    data: this.data,
    method: this.method
  }
}

然后,在子组件中,你可以像这样使用inject:

inject: ['data', 'method']

现在,子组件就可以使用父组件提供的数据和方法,而不需要通过props或事件来传递。

4. 再看一个稍微复杂点的,相信更好理解。

  • 在 App.vue 文件中,我们使用 provide 来提供一个名为 “theme” 的数据,这个数据是一个字符串类型的变量,它的值为 “light”。同时也包含了一个名为 “changeTheme” 的方法,用来改变主题。
<template>
  <div :class="currentTheme">
    <h1>My App</h1>
    <button @click="changeTheme">改变主题颜色</button>
    <child-component></child-component>
  </div>
</template>

<script>
import {
    
     ref, provide } from 'vue'
import ChildComponent from './ChildComponent.vue'

export default {
    
    
  components: {
    
    
    ChildComponent
  },
  setup() {
    
    
    const currentTheme = ref('light')

    function changeTheme() {
    
    
      currentTheme.value = currentTheme.value === 'light' ? 'dark' : 'light'
    }

    provide('theme', currentTheme)
    provide('changeTheme', changeTheme)

    return {
    
    
      currentTheme,
      changeTheme,
    }
  },
}
</script>

在 ChildComponent.vue 文件中,我们使用 inject 来注入父组件提供的 "theme" 数据和 "changeTheme" 方法,并将它们分别存储在名为"currentTheme""changeTheme"的变量中。

<template>
  <div :class="currentTheme">
    <p>This is the child component</p>
  </div>
</template>

<script>
import {
    
     inject } from 'vue'

export default {
    
    
  setup() {
    
    
    const currentTheme = inject('theme')
    const changeTheme = inject('changeTheme')

    return {
    
    
      currentTheme,
      changeTheme,
    }
  },
}
</script>

这样,通过 provideinject,我们就可以在父组件和子组件之间传递数据和方法了。在本例中,点击按钮会改变主题,同时在子组件中也能看到主题的变化效果。
在这里插入图片描述

14. vuex中 mutaiton 和 actiond 的区别?

  • 在 Vuex 中,mutation 和 action 都用于管理应用程序状态的变化。它们之间的主要区别是:
  1. Mutation 是同步操作,而 Action 是异步操作。Mutation 可以直接修改状态,而 Action 不能修改状态,需要提交 Mutation 来修改状态。
  2. Mutation 用于更新状态,通常被组件中的方法调用,直接更新应用程序的状态;Action 则可以包含任意异步操作,例如 API 调用、延迟操作等,并在完成后提交 Mutation 更新状态。
  3. Mutation 必须是纯函数,即不依赖外部状态或产生副作用;而 Action 可以执行异步逻辑并且不必是纯函数。

因此,当我们需要执行异步操作或需要根据其他条件来执行状态变更时,应该使用 Action。而当我们需要直接更新状态时,应该使用 Mutation。

  • 通常情况下,将设置Token放在Action中比较合适。这是因为在处理身份验证、登录等操作时,我们需要进行异步处理来与后台服务器进行通信,并在响应返回后更新状态中的token。

例如:

// 定义 credentials 代表用户的登录凭证
// 包括用户名和密码等信息。
const credentials = {
    
    
  username: 'your_username',
  password: 'your_password'
};
actions: {
    
    
  // 通过使用 commit 方法来触发 mutation
  login({
     
      commit }, credentials) {
    
    
    return axios.post('/api/login', credentials)
      .then(response => {
    
    
        const token = response.data.token;
        commit('setToken', token);
        localStorage.setItem('token', token); // 将token存储在本地
      })
      .catch(error => {
    
    
        console.log(error);
      });
  }
},
mutations: {
    
     // 修改 state中 token的状态
  setToken(state, token) {
    
    
    state.token = token;
  }
}

15. JS 严格模式有什么特点?

  • JavaScript 严格模式(strict mode)是 ECMAScript 5 引入的一种特殊模式,它可以让 JavaScript 的编写和执行更加严格,减少错误和不安全的行为。以下是严格模式的一些特点:
  1. 变量必须先声明后使用。在严格模式下,如果使用未声明的变量,会抛出 ReferenceError 错误。

  2. 函数内部的 this 值不能指向全局对象。在严格模式下,如果在函数内部没有正确地设置 this,则其值将为 undefined

<script>
   'use strict' 
   function fn(){
    
    
         console.log('this',this) // undefined
   }  fn()
</script>
  1. 禁止删除不可删除的属性。在严格模式下,调用 delete 操作符尝试删除不可删除的属性时,会抛出一个错误。

  2. 禁止修改只读属性。在严格模式下,调用 Object.defineProperty() 方法尝试修改只读属性时,会抛出一个错误。

  3. 禁止使用八进制字面量。在严格模式下,数字前缀为 0 的字面量被视为无效的,并抛出一个错误。

  4. eval() 中声明的变量和函数不会影响到当前作用域。在严格模式下,使用 eval() 运行代码时,它创建的变量和函数不会污染当前作用域。

<script>
'use strict' 
var x = 10;
eval(`var x = 20; console.log('in eval', x);`) 
// eval有自己的作用域,上面代码打印 in eval 20
console.log('out eval', x); // 打印 out eval 10
</script>
  1. 禁止使用 with 语句。在严格模式下,使用 with 语句会抛出一个错误。
<script>
'use strict' 
const obj = {
    
    x:100,y:200}
with(obj){
    
    
    console.log(x,y) // 会报错,不开启严格模式,打印100 200
}
</script>
  1. 函数的参数名不能重复。在严格模式下,函数的参数名不能重复,否则会抛出一个错误。

总之,JavaScript 严格模式可以使开发者写出更加规范、可靠、安全的代码,并减少一些常见的错误和不安全的行为。建议在编写 JavaScript 代码时启用严格模式。
在这里插入图片描述

16. HTTP 跨域请求时为何要发送 options 请求?

  • jsonp是一种跨域数据传输的方式,它允许在客户端和服务端之间进行数据交互。
  • 其原理是利用script标签可以跨域加载资源的特性,将需要获取的数据作为参数传递给服务端,服务端返回一段JavaScript代码并执行,这段代码会调用一个回调函数并将数据作为参数传入该函数中。
  • 使用window对象来定义全局回调函数存在一些问题。首先,如果多个页面同时使用相同的回调函数名称,就会出现命名冲突的问题。其次,如果回调函数中的代码有错误,可能会导致整个页面崩溃。
  • 因此,更好的做法是使用一个独立的命名空间来定义回调函数,例如:
var myNamespace = {
    
    };

myNamespace.myCallback = function(data) {
    
    
  console.log('Received data:', data);
}

var script = document.createElement('script');
script.src = 'https://example.com/data?callback=myNamespace.myCallback';
document.head.appendChild(script);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_46426412/article/details/130717177
今日推荐