20 个基础实用的 JavaScript 技巧

news2025/1/11 10:49:17

1.确定对象的数据类型

function myType(type) {  return Object.prototype.toString.call(type).slice(8, -1);

使用Object.prototype.toString,通过传入不同类型的判断返回不同的判断函数,一行代码,简洁优雅灵活;

2.循环遍历数组map方法

const myMap = function (fn, context) {  let arr = Array.prototype.slice.call(this);  let resultArr = Array();  for (let i = 0; i < arr.length; i++) {    if (!arr.hasOwnProperty(i)) continue;    resultArr[i] = fn.call(context, arr[i], i, this);  }  return resultArr;};
Array.prototype.myMap = myMap;let arr = [1, 2, 3];console.log(arr.myMap((item) => item + 1)); // 2,3,4

值得注意的是,map第二个参数在第一个参数回调中指向this。如果第一个参数是箭头函数,则第二个 this 的设置无效。

3.循环遍历数组过滤方法

const myFilter = function (fn, context) {    let arr = Array.prototype.slice.call(this)    let resultArr = []    for (let i = 0; i < arr.length; i++) {        if(!arr.hasOwnProperty(i)) continue;         fn.call(context, arr[i], i, this) && resultArr.push(arr[i])    }    return resultArr}Array.prototype.myFilter = myFilterlet arr = [1, 2, 3]console.log(arr.myFilter(item => item === 2)) // [2]

4.使用reduce实现数组过滤方法

const myFilter2 = function (fn, context) {    return this.reduce((total, current, index) => {        return fn.call(context, current, index, this) ? [...total, current] : [...total]    }, [])}

5.遍历数组的一些方法

const mySome = function (fn, context) {  let arr = Array.prototype.slice.call(this);  // The empty array returns false directly, and the every method of the array returns true conversely  if (!arr.length) return false;  for (let i = 0; i < arr.length; i++) {    if (!arr.hasOwnProperty(i)) continue;    let res = fn.call(context, arr[i], i, this);    if (res) return true;  }  return false;};
Array.prototype.mySome = mySome;
let arr = [1, 2, 3];console.log(arr.mySome((item) => item === 2));

执行 some 的数组如果是空数组总是返回 false,而另一个数组的 every 方法中的数组如果是空数组总是返回 true。

6.通过循环实现数组的reduce方法

Array.prototype.myReduce = function (fn, initialValue) {    let arr = Array.prototype.slice.call(this)    let startItem    let startIndex    if (initialValue === undefined) {        // Finds the element and subscript of the first non-empty (real) unit        for (let i = 0; i < arr.length; i++) {            if (!arr.hasOwnProperty(i)) continue            startIndex = i            startItem = arr[i]            break        }    } else {        startItem = initialValue    }    // The starting point for traversal is the real element after the real element found in the previous step    // Each iteration skips the elements of the empty cell    for (let i = ++startIndex || 0; i < arr.length; i++) {        if (!arr.hasOwnProperty(i)) continue        startItem = fn.call(null, startItem, arr[i], i, this)    }    return startItem}
Array.prototype.myReduce = myReduce

let arr = [1, 2, 3]
console.log(arr.myReduce((acc, cur) => acc + cur)) // 6console.log(arr.reduce((acc, cur) => acc + cur)) // 6

7.使用reduce实现array的flat方法

// reduce implements array.prototype.flat, Array flatconst myFlat = function (depth = 1) {    let arr = Array.prototype.slice.call(this)    if (depth === 0) return arr    return arr.reduce((total, current) => {        if (Array.isArray(current)) {            // You need to bind this with call, otherwise it points to the window            return [...total, ...myFlat.call(current, depth-1)]        } else {            return [...total, current]        }    }, [])}
Array.prototype.myFlat  = myFlatlet arr = [1, 2, [3, 4, [5, 6,['a','b','c',['d']], 7, 8], 9], 10, 11, 12, [13, 14]]
console.log(arr.myFlat())

因为myFlat依赖这个指向,所以需要在reduce遍历的时候指定myFlat的这个指向;否则默认指向window,会报错。

当数组的元素还是数组时,使用ES6的扩展运算符对其进行降维(ES5中可以使用concat方法)。但是数组元素内部可能有嵌套数组,所以需要递归调用selfFlat。

同时,原生的 Flat 方法支持一个深度参数来表示降维的深度。默认值为1,表示数组减少一维。

传递 Infinity 将传递的数组变成一维数组:

8. 实现 ES6 类语法

function Animal(name) {    this.name = name}
Animal.staticFunc = function () {    console.log('staticFunc')}Animal.prototype.sleep = function () {    console.log('animal is sleeping')}
//Parasitic combinatorial inheritance + inheritance between constructorsfunction Dog(name, color) {    Animal.call(this, name)    this.color = color}
function inherit(subType, superType) {    //Due to the nature of JavaScript reference types and functions passing by value, you cannot change the reference address of subType    subType.prototype = Object.create(superType.prototype, {        constructor: {            enumerable: false,            configurable: true,            writable: true,            // Points to subclasses, consistent with the default inheritance behavior            value: subType        }    })    //The child constructor inherits the parent constructor (the child inherits the static methods and static properties of the parent class)    Object.setPrototypeOf(subType, superType)}
inherit(Dog, Animal)
//You need to add the prototype method to Dog after inheritance, otherwise it will be overwrittenDog.prototype.barking = function () {    console.log('wang!')}

let brownTeddy = new Dog('teddy', 'brown')Dog.staticFunc()console.log(brownTeddy)brownTeddy.sleep()brownTeddy.barking()

Create 方法创建一个空 Object,并从 Object.create 方法的参数中继承这个空 Object。然后让子类的原型(subType)等于空对象,就可以实现子类的原型等于空对象,空对象等于父类的继承原型。

Object.create 支持第二个参数,它为生成的空对象定义属性和属性/访问器描述符。我们可以给这个空对象一个更符合默认继承行为的构造函数属性。它也是一个不能枚举的内部属性(Enumerable: False)。

ES6 类允许子类从父类继承静态方法和静态属性,而普通的寄生组合继承只能在实例之间实现。对于类到类的继承,需要定义额外的方法。

这里我们使用 Object.setProtoTypeof 将 superType 设置为 subType 的原型,从而能够从父类继承静态方法和静态属性。

9. 函数的焦化

const display = (a, b, c, d, e, f) => [a, b, c, d, e, f];
/** * @description Currization of a function (How many times a currization function needs to be executed according to the number of parameters of the function before currization) * @param {function} fn -The Currified function */
function curry(fn) {    if (fn.length <= 1) return fn;    const generator = (...args) => {        if (fn.length === args.length) {            //Executes fn and returns the execution result            return fn(...args)        } else {            return (...args2) => {                //Return generator function                return generator(...args, ...args2)            }        }    }    return generator}
const curriedDisplay = curry(display);console.log("curriedDisplay", curriedDisplay(1)(2)(3)(4)(5)(6));

Currization 是函数式编程中的一项重要技术,该技术将一个接受多个参数的函数转换为一系列接受一个参数的函数。

函数式编程 compose 另一个重要的功能,并且要能够进行函数组合,函数的组合只接受一个参数,所以如果你必须接受多个函数的需求并且需要使用 compose 函数组合,就需要使用 compose 的部分 curry 准备复合函数,让它总是只接受一个参数。

10. 函数修正(占位符支持)

const curry3 = (fn, placeholder = "_") => {    curry3.placeholder = placeholder    if (fn.length <= 1) return fn;    let argsList = []    const generator = (...args) => {        let currentPlaceholderIndex = -1         args.forEach(arg => {            let placeholderIndex = argsList.findIndex(item => item === curry3.placeholder)            if (placeholderIndex < 0) {                currentPlaceholderIndex = argsList.push(arg) - 1                               // (1,'_')('_',2)            } else if (placeholderIndex !== currentPlaceholderIndex) {                argsList[placeholderIndex] = arg            } else {                 argsList.push(arg)            }        })        let realArgsList = argsList.filter(arg => arg !== curry3.placeholder)         if (realArgsList.length >= fn.length) {            return fn(...argsList)        } else {            return generator        }    }
    return generator}
const curriedDisplay3 = curry3(display);console.log("curriedDisplay3", curriedDisplay3('_', 2)(1, '_', 4)(3, '_',)('_', 5)(6)(7, 8))

如果当前轮参数包含占位符,则将其放置在内部保存数组的末尾。当前轮的元素不填充当前轮参数的占位符,而只填充之前传入的占位符。

11. 斐波那契数列及其优化

const speed = function (fn, num) {    console.time('time')    let value = fn(num)    console.timeEnd('time')    console.log(`result:${value}`)}
/** * @description Fibonacci numbers * @param {number} n -Number of positions * @return {number} The argument corresponds to a number in a sequence **/let fibonacci = function (n) {    if (n < 1) throw new Error('Parameter is wrong')    if (n === 1 || n === 2) return 1    return fibonacci(n - 1) + fibonacci(n - 2)}
speed(fibonacci, 40)

//Memory functionconst memory = function (fn) {    let obj = {}    return function (n) {        if (obj[n] === undefined) obj[n] = fn(n)        return obj[n]    }}fibonacci = memory(fibonacci)
speed(fibonacci, 40)

/** * @description Fibonacci dynamic programming version (Optimal) **/function fibonacci_DP(n) {    let res = 1    if (n === 1 && n === 2) return res    n = n - 2    let cur = 1    let pre = 1    while (n) {        res = cur + pre        pre = cur        cur = res        n--    }    return res}
speed(fibonacci_DP, 40)

使用函数内存,可以为经常依赖先前结果的计算节省大量时间,例如斐波那契数列。缺点是闭包中的 obj 对象占用了额外的内存。

另外,动态规划的空间复杂度比前者低,也是比较推荐的方案。

12.实现绑定方法

const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && obj !== null
// Implement a simple bindconst myBind = function (bindTarget, ...args1) {    if (typeof this !== 'function') throw new TypeError('Bind must be called on a function')    const originFunc = this    const boundFunc = function (...args2) {        // Calls using the new keyword return a new object        if (new.target) {            let res = originFunc.call(this, ...args1, ...args2)            //If the constructor returns an object, that object is returned            if (isComplexDataType(res)) return res            //Otherwise, the newly created object is returned            return this        } else {            return originFunc.call(bindTarget, ...args1, ...args2)        }    }    if (originFunc.prototype) {        boundFunc.prototype = originFunc.prototype    }
    const desc = Object.getOwnPropertyDescriptors(originFunc)    Object.defineProperties(boundFunc, {        length: desc.length,        name: Object.assign(desc.name, {            value: `bound ${desc.name.value}`        })    })    return boundFunc}

实现函数的bind方法的核心使用调用绑定指向this,同时考虑到其他情况如:

  • 当bind返回的函数作为构造函数被new调用时,绑定值失效,变为new指定的对象。

  • 定义绑定函数的length和name属性(不可枚举的属性)。

  • 绑定函数的prototype必须指向prototype原函数的 。

13.实现调用方法

const myCall = function (context, ...args) {    let func = this    context || (context = window)    if (typeof func !== 'function') throw new TypeError('this is not function')    let caller = Symbol('caller')    context[caller] = func    let res = context[caller](...args)    delete context[caller]    return res}

原理是将函数作为context传入参数的属性执行。ES6 Symbol 类型用于防止属性冲突。

14.简单的CO模块

//Self-executing generator functions
const data = "{a:1,b:2}";const data2 = "{c:3,d:4}";const data3 = "{e:5,f:6}";
const api = function (data) {  return new Promise((resolve) => {    setTimeout(() => {      resolve(data);    }, 1000);  });};
function* func() {  let res = yield api(data);  console.log(res);  let res2 = yield api(data2);  console.log(res2);  let res3 = yield api(data3);  console.log(res3);  console.log(res, res2, res3);}
function makePromisify(source) {  if (source.then && typeof source.then === "function") return source;  return Promise.resolve(source);}
function run(generatorFunc) {  let it = generatorFunc();  let result = it.next();
  return new Promise((resolve, reject) => {    const next = function (result) {      if (result.done) {        return resolve(result.value);      }      result.value = makePromisify(result.value);      result.value        .then((res) => {          let result = it.next(res);          //Recursively execute the next function          next(result);        })        .catch((err) => {          reject(err);        });    };    next(result);  });}
run(func);

run函数接受一个生成器函数,每次run函数包裹的生成器函数遇到yield关键字时停止,当yield后的promise成功解析时,自动调用next方法执行到下一个yield关键字。

最后,每次成功解析一个promise,都会解析下一个promise。

当所有的结果都解析成功后,所有解析的结果都会被打印出来,演变成今天最常用的 async/await 语法。

15.功能防抖

/** * @description debounce * @param {Function} func -Functions that need function stabilization * @param {Number} time -Delay time * @param {Options} options -Configuration items * @return {Function} -A function that has been shaken out **/
/** * @typedef {Object} Options -Configuration items * @property {Boolean} leading -Whether an extra trigger is required to start * @property {Boolean} trailing -Whether an additional trigger is required after the end * @property {this} context -this **/
const debounce = (func, time = 20, options = {    leading: true,    context: null}) => {    let timer;    const _debounce = function (...args) {        if (timer) {            clearTimeout(timer)        }        if (options.leading && !timer) {            timer = setTimeout(null, time)            func.apply(options.context, args)        }else{            timer = setTimeout(() => {                func.apply(options.context, args)                timer = null            }, time)        }    };        _debounce.cancel = function () {        clearTimeout(timer)        timer = null    };    return _debounce};

16.函数节流

/** * @description throttle * @param {Function} func -Functions that require function throttling * @param {Number} time -Delay time * @param {Options} options -Configuration items * @return {Function} -经过节流处理的函数 **/
/** * @typedef {Object} Options -Configuration items * @property {Boolean} leading -Whether an extra trigger is required to start * @property {Boolean} trailing -Whether an additional trigger is required after the end * @property {this} context -this **/
const throttle = (func, time = 17, options = {    // leading 和 trailing 无法同时为 false    leading: true,    trailing: false,    context: null}) => {    let previous = new Date(0).getTime()    let timer;    const _throttle = function (...args) {        let now = new Date().getTime();
        if (!options.leading) {            if (timer) return            timer = setTimeout(() => {                timer = null                func.apply(options.context, args)            }, time)        } else if (now - previous > time) {            func.apply(options.context, args)            previous = now        } else if (options.trailing) {            clearTimeout(timer)            timer = setTimeout(() => {                func.apply(options.context, args)            }, time)        }    };    _throttle.cancel = () => {        previous = 0;        clearTimeout(timer);        timer = null    };    return _throttle};

添加尾随选项以指示是否在序列结束时触发附加事件。

17. 图片的延迟加载

// getBoundingClientRect lazy Loadlet imgList1 = [...document.querySelectorAll(".get_bounding_rect")]let num = imgList1.length
let lazyLoad1 = (function () {    let count = 0    return function () {        let deleteIndexList = []        imgList1.forEach((img,index) => {            let rect = img.getBoundingClientRect()            if (rect.top < window.innerHeight) {                img.src = img.dataset.src                // Add the image to the remove list after loading successfully                deleteIndexList.push(index)                count++                if (count === num) {                    //Unbind the Scroll event when all images are loaded                    document.removeEventListener('scroll',lazyLoad1)                }            }        })        // Delete images that have been loaded        imgList1 = imgList1.filter((_,index)=>!deleteIndexList.includes(index))
    }})()
// The throttling function of throttle.js is referenced herelazyLoad1 = proxy(lazyLoad1, 100)
document.addEventListener('scroll', lazyLoad1)// Manually load the image once. Otherwise, the image on the first screen cannot be loaded without triggering scrollinglazyLoad1()


// intersectionObserver lazy Loadlet imgList2 = [...document.querySelectorAll(".intersection_observer")]
let lazyLoad2 = function () {    // instantiation observer    let observer = new IntersectionObserver(entries => {        entries.forEach(entry => {            if (entry.intersectionRatio > 0) {                entry.target.src = entry.target.dataset.src                observer.unobserve(entry.target)            }        })    })    imgList2.forEach(img => {        observer.observe(img)    })}
lazyLoad2()

getBoundClientRect 的实现监听滚动事件(建议为监听事件添加节流)。图片加载完成后,会从 img 标签组成的 DOM 列表中删除。最后,加载监听器事件后,所有图像都需要解除绑定。

IntersectionObserver 是通过实例化一个intersectionObserver 并使其观察所有IMG 标签来实现的。

当img标签进入查看区域时,实例化时执行回调。 同时传入一个回调,保存实例来观察所有元素的某种状态,比如每个元素的边界,当前元素对应的DOM节点,当前元素进入查看区域的比例。每当一个元素进入查看区域时,将真实图像分配给当前 IMG 标签,同时不观察它。

18. 新关键字

const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && obj !== null
const myNew = function (fn, ...rest) {    let instance = Object.create(fn.prototype)    let res = fn.call(instance, ...rest)    return isComplexDataType(res) ? res : instance}
function Person(name, sex) {    this.name = name    this.sex = sex}

let newPerson = new Person('tony', 'woman')let myNewPerson = myNew(Person, 'tony1', 'man')
console.log(newPerson)console.log(myNewPerson)

19.实现对象分配

"use strict" 
const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && obj !== null

const myAssign = function (target, ...source) {    if (target == null) throw new TypeError('Cannot convert undefined or null to object')    return source.reduce((acc, cur) => {        isComplexDataType(acc) || (acc = new Object(acc));         if (cur == null) return acc;         [...Object.keys(cur), ...Object.getOwnPropertySymbols(cur)].forEach(key => {            acc[key] = cur[key]        })        return acc    }, target)}
Object.myAssign = myAssign

let target = {    a: 1,    b: 1}
let obj1 = {    a: 2,    b: 2,    c: undefined}
let obj2 = {    a: 3,    b: 3,    [Symbol("a")]: 3,    d: null}
console.log(Object.myAssign(target, obj1, obj2))console.log(Object.myAssign("abd", null, undefined))

20. 实例化

const myInstanceof = function (left, right) {    let proto = Object.getPrototypeOf(left)    while (true) {        if (proto == null) return false        if (proto === right.prototype) {            return true        }        proto = Object.getPrototypeOf(proto)    }}
console.log(myInstanceof({}, Array))

结论

到这里,我们我们终于得到它了。20 个出色的技巧,可帮助您编写更好、更高效的代码。阅读前你知道多少?

如果您觉得这很有用,请务必点赞、评论和分享。

谢谢!

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

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

相关文章

HylicOS --- 内存抽象

HylicOS已经完成了部分硬件抽象层的工作&#xff0c;包括MMU的初始化并对虚拟内存到物理内存做了映射&#xff0c;创建了页表目录。对串口进行了初始化&#xff0c;实现了printk格式化打印函数&#xff0c;方便了日志输出和程序调试。建立了异常向量表。 现在要做的是内存管理…

复方一枝蒿复合磷脂/IgG二性霉素B/阿糖胞苷修饰载甲氨喋呤/酶促合成半乳糖配体脂质体制备

小编今天为大家分享的科研知识是复方一枝蒿复合磷脂/IgG二性霉素B/阿糖胞苷修饰载甲氨喋呤/酶促合成半乳糖配体脂质体&#xff0c;一起来看&#xff01; 点击输入图片描述&#xff08;最多30字&#xff09; 复方一枝蒿复合磷脂脂质体&#xff1a; 采用硫酸铵梯度法制备复方一枝…

gunicorn走私漏洞

gunicorn走私漏洞 源码&#xff1a;https://github.com/benoitc/gunicorn漏洞定位&#xff1a;https://github.com/benoitc/gunicorn/blob/20.x/gunicorn/http/message.py#142 漏洞分析 只要header里面存在Sec-Websocket-Key1 那么就将content_length强制赋值为8 比较简单直接…

【java】java JSR 269 自定义注解实战 Lombok @Data注解

1.概述 本节会演示一个实际的例子,使用JSR 269 API为类中的字段自动生成get、set 方法。首先定义一个自定义注解类Data,如下所示。 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import

智能工业之数据采集

现状 工业物联网飞速发展&#xff0c;但是相对于实时IT技术还是明显滞后的。个人理解&#xff0c;有两点原因&#xff1a;一是因为涉及的知识面也比较广&#xff0c;工业物联网开发成本比较高&#xff0c;不像做一个纯软件的管理系统&#xff0c;坐在电脑前借助开源框架就能完成…

你好,Ultrachess 里程碑更新了。

Cartesi Labs 资助的完全去中心化国际象棋项目即将来到你的面前。在10月&#xff0c;我们宣布了第一个由Cartesi Rollup 技术支持的完全链上国际象棋应用程序Ultrachess。Ultrachess允许用户将真正的价值放在赌注上&#xff0c;并在下棋时考虑的不仅仅是他们的隐藏分值。此外&…

Java中的StringBuilder类

目录 一、介绍 二、StringBuilder类的体系图 三、StringBuilder的常用方法 四、String、StringBuffer和StringBuilder比较 1、效率比较 2、如何选择&#xff1f; 一、介绍 StringBuilder也是lang包中的类&#xff0c;即java.lang.StringBuilder类。它也是一个可变的字符序…

设计模式原则-三-依赖倒转原则

设计模式原则---依赖倒转原则依赖倒转原则一 官方定义基本介绍二 案例演示普通方式实现**解决方案****案例分析****案例总结**依赖倒转原则方式实现**解决方案**案例分析**案例总结**注意事项&细节三 依赖关系传递方式一、通过接口传递二、通过构造方法传递三、通过set()方…

原来 Android 的 R 文件里还有这么多道道

前言 nonTransitiveRClass&#xff1a;非传递性 R 类的属性&#xff0c;在 gradle.properties 文件里使用。 不少开发者可能听过它&#xff0c;但了解可能仅限于是对 R 文件做了优化&#xff0c;甚至以为它可以解决资源冲突&#xff01;但它到底做了什么优化、能否解决资源冲突…

Manacher算法

0、概括 Manacher算法用于求解字符串中最长回文子串问题。 Manacher算法的核心&#xff1a; 理解回文半径数组&#xff1b;理解所有中心的回文最右边界 R&#xff0c;和取得 R 时的中心点 C&#xff1b;理解 L...(i)...C...(i)...R 的结构&#xff0c;以及根据 i′ii′ 回文长…

C-RNN-GAN:具有对抗训练的连续循环神经网络2016--生成音乐

C-RNN-GAN: Continuous recurrent neural networks with adversarial training 2016 Abstract 生成对抗网络已被提出作为一种有效训练深度生成神经网络的方法。我们提出了一种生成对抗模型&#xff0c;它适用于连续的序列数据&#xff0c;并通过在古典音乐集合上训练它来应用它…

计算机毕设Python+Vue校园学生体温管理系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

相见恨晚,Git这些功能太好用了

程序员宝藏库&#xff1a;https://gitee.com/sharetech_lee/CS-Books-Store 作为一名开发者&#xff0c;想必绝大多数同学都无法绕开Git。 作为一款工具&#xff0c;我认为它和word、powerpoint、Excel这些办公工具一样。 对于一部分同学&#xff0c;会一些基本的用法&#x…

【经验帖】项目经理的核心价值:以目标为导向做正确的事

项目经理小李的年终汇报心路历程&#xff08;心情犹如坐过山车&#xff0c;起起落落最后一蹶不振。&#xff09; 汇报前&#xff1a; 终于到年终汇报的日子了&#xff0c;毕竟我负责的项目任务从来没有延期过&#xff0c;都是按时完成&#xff0c;这次肯定得加薪了&#xff01…

[附源码]Node.js计算机毕业设计公租房管理系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

module命名空间

为什么要有namespaced命名空间&#xff1f; 默认情况下&#xff0c;模块内部的action、mutation和getter都是在全局命名空间。 假设两个modules内部有同名的action、mutation和getter&#xff0c;则vuex会报错。 namespaced作用&#xff1a;保证模块内部的高封闭性&#xff0c;…

021 | 阴离子诱导的系列双核镝配合物的合成及磁性质 | 大学生创新训练项目申请书 | 极致技术工厂

研究目的 近十几年来&#xff0c;随着科技的飞速发展&#xff0c;单分子磁体材料涉及的应用领域越来越宽广。众所周知&#xff0c;单分子磁体材料作为信息存储的基础对信息产业的发展具有一定的意义。此外&#xff0c;单分子磁体在超高密度储存、自旋电子器件、量子计算机等领域…

旅游住宿网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 网站前台&#xff1a;网站介绍、帮助信息、旅游资讯。景点信息、酒店信息 管理员功能&#xff1a; 1、管理网站介绍、帮…

day22【代码随想录】在每个树行中找最大值、填充每个节点的下一个右侧节点指针、二叉树的最大深度、二叉树的最小深度

文章目录前言一、在每个树行中找最大值&#xff08;力扣515&#xff09;二、填充每个节点的下一个右侧节点指针&#xff08;力扣116&#xff09;三、二叉树的最大深度&#xff08;力扣104&#xff09;1、非递归求解2、递归求解四、 二叉树的最小深度&#xff08;力扣111&#x…

【前端开发学习】4.JavaScript

文章目录1 JavaScript1.1 代码位置1.2 存在形式1.3 注释1.4 变量1.5 字符串类型案例&#xff1a;走马灯1.5 数组案例&#xff1a;动态数据1.6 对象&#xff08;字典&#xff09;案例&#xff1a;动态表格1.7 条件语句1.8 函数2 DOM2.1 事件绑定1 JavaScript 一门编程语言&…