什么是开包和闭包
开包:开包也可以叫函数柯里化,是将接收多个参数的函数转换成一系列使用单个参数的函数
function add(x, y) {
return x + y
}
function addToX(x) {
return function (y) {
return add(x, y)
}
}
const addFive = addToX(5);
addFive(2); // 7
闭包 :
- 函数嵌套函数
- 函数内部可以引用外部的参数和变量
- 参数和变量不会被垃圾回收机制回收,会永远留驻在内存中
闭包优点:长时间储存变量在内存中,减少全局变量的污染,加强封装性
闭包缺点:占用更多的内存导致内存泄漏,或性能下降
闭包不是回调,回调也不是闭包,回调是函数内执行另一个函数,闭包是函数内返回另一个函数,且返回了父级函数的作用域变量
垃圾回收机制:简单的说,当一个函数被执行完后,其作用域会被收回
function counter() {
let count = 0
return () => {
return ++count
}
}
const c = counter()
console.log(c()) //1
console.log(c()) //2
console.log(c()) //3
原型链
- 原型:portoType属性就是函数的原型
- 原型链:所有对象都有原型,而原型本身就是对象,所以原型也有自己的原型对象,就形成了原型链
- 如果对象本身没有属性,就会去原型链上找
- object原型对象的原型值为null
防抖和节流
- 防抖:触发事件后在N秒内只执行一次,如果再次触发则重新计算函数执行时间(每多少秒内只能执行一次,再次点击重新算时间)
- 节流:每次触发事件后的时间间隔至少要大于等于N秒,不会重置计时(每多少秒可以触发一次)
递归
什么是递归
- 自身调用自身
- 至少应该有一个结束条件
使用场景
- 多层级结构,并且每个层级大致相同,而且前后还有关联性
递归比普通函数效率低,日常还是少用吧
function walk(step){
if(step == 0){
console.log('结束了')
}else{
step--
walk(step)
}
}
walk(100) //默认传了100
去重
- new Set() 和扩展运算符结合
let arr = [1,2,3,4,5,1,2,3,4,5,6]
let setArr = new Set(arr)
console.log(setArr) //返回set数据结构 Set(3) {1,2,3,4,5,6,7}
//es6的 ... 运算符
console.log([...setArr]) //输出 [1, 2, 3, 4, 5, 6]
console.log(...setArr) //输出 1, 2, 3, 4, 5, 6
- indexOf
let arr1 = [1,2,3,4,5,1,2,3,4,5,6]
let arr2 = []
for(let i in arr1){
if(arr2.indexOf(arr1[i]) === -1){ //如果数组中没有当前数值,indexOf 则返回-1,
arr2.push(arr1[i])
}
}
console.log(arr2)
- 双层循环,外层循环数组1,内层循环数组2,数组2中有则跳过,没有则push
封装过的组件
- 图片上传组件
- 轮播图组件
- 日期选择器
- 头部,侧边栏,底部,导航栏组件等
封装的方法有那些
vue组件之间通讯
V2
- 父子组件通讯:通过 props 将数据从父组件传到子组件,子组件修改参数后通过$emit方法触发事件告诉父组件
- 子父组件通讯:通过在子组件中使用 $emit 方法触发一个事件,在父组件中使用 $on 方法监听该事件,从而实现子组件向父组件通信。
- 兄弟组件通讯:可以通过一个父组件作为中介,在父组件定义变量,通过props分别传给两个子组件,其中一个子组件修改了变量后,通过$emit传回父组件,在逐级传递给另一个子组件
- 无关组件通讯:可以使用事件总线(Event Bus)实现无关组件间的通讯,也就是一个空的vue实例(事件总线)上定义一个事件,然后任意组件通过$emit 和 $on方法分别触发和监听该事件来实现通讯
- Vuex :Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,通过共享一个全局状态对象,实现组件之间的数据共享和通信。Vuex 将所有的状态都保存在 state 中,然后通过 mutations 修改 state,最后在 actions 中触发 mutations 从而修改 state 中的数据,最终通过 getters 获取 state 中的数据。
es6 新增的特性
1. let和const
都有作用域,不能同一个作用域重复声明,const 声明变量必须有默认值
2. 字符串模板 “${}
”
3. 箭头函数 “()=>{}”
4. 扩展运算符 “…”
5.结构赋值
方便数据提取和赋值方式,他可以从数组或者对象中提取值,然后单独赋值给变量
数组的结构赋值
let [a, b, c] = [1, 2, 3];
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
// 可以跳过某些位置
let [x, , z] = [4, 5, 6];
console.log(x); // 4
console.log(z); // 6
// 可以使用剩余操作符 `...` 收集剩余的元素
let [m, n, ...rest] = [7, 8, 9, 10, 11];
console.log(m); // 7
console.log(n); // 8
console.log(rest); // [9, 10, 11]
对象的解构赋值
let { name, age } = { name: "John", age: 30 };
console.log(name); // John
console.log(age); // 30
// 可以给变量起不同的名字
let { name: myName, age: myAge } = { name: "Jane", age: 25 };
console.log(myName); // Jane
console.log(myAge); // 25
// 可以设置默认值
let { city = "New York" } = {};
console.log(city); // New York
6.map/set
Map:Map 是键值对的集合,其中键可以是任何类型的值(包括对象),而不仅仅是字符串。
// 创建
let myMap = new Map();
myMap.set("key1", "value1");
myMap.set(2, "value2");
myMap.set({ name: "John" }, "value3");
// 获取
console.log(myMap.get("key1"));
console.log(myMap.get(2));
console.log(myMap.get({ name: "John" }));
// 检查键是否存在
console.log(myMap.has("key1"));
// 删除键值对
myMap.delete("key1");
// 获取 Map 的大小
console.log(myMap.size)
// 遍历 Map
for (let [key, value] of myMap) {
console.log(key + ': ' value);
}
Set:Set 是一种不允许重复值的数据结构。
// 创建
let mySet = new Set();
mySet.add(1);
mySet.add(2);
mySet.add(2); // 重复添加不会有效果
mySet.add("Hello");
// 检查元素是否存在
console.log(mySet.has(1));
// 删除元素
mySet.delete(1);
// 获取 Set 的大小
console.log(mySet.size);
// 遍历 Set
for (let item of mySet) {
console.log(item);
}
7.symbol
在 ES6 中,Symbol 是一种新的基本数据类型,它的主要目的是创建独一无二的值,通常用于对象的属性名,以避免属性名冲突。
let sym1 = Symbol();
let sym2 = Symbol("description"); // 可以提供一个可选的描述字符串
8.promise
9.类 class
10.剩余参数
ES6 中的剩余参数语法允许将不定数量的参数表示为一个数组。
其语法形式为:在函数的最后一个命名参数前加上三个点(…),后面跟着参数名,例如:function(a, b,…theArgs){ // 函数体 } ,在这个例子中,theArgs 将收集该函数的第三个参数及以后的所有剩余参数。
function fun1(...theArgs) {
alert(theArgs.length);
}
fun1(); // 弹出"0", 因为 theArgs 没有元素
fun1(5); // 弹出"1", 因为 theArgs 只有一个元素
fun1(5, 6, 7); // 弹出"3", 因为 theArgs 有三个元素
function multiply(multiplier,...theArgs) {
return theArgs.map(function(element) {
return multiplier * element;
})
}
var arr = multiply(2, 1, 2, 3);
console.log(arr); // (2, 4, 6)
function sortRestArgs(...theArgs) {
var sortedArgs = theArgs.sort();
return sortedArgs;
}
alert(sortRestArgs(5, 3, 7, 1)); // 弹出 1, 3, 5, 7
// 剩余参数可以被解构
function f(...(a, b, c)) {
return a + b + c;
}
f(1) // NaN (b 和 c 是 undefined)
f(1, 2, 3) // 6
f(1, 2, 3, 4) // 6 (第四个参数没有被解构)
11.模块化
ES6 引入了模块化的概念,这使得 JavaScript 代码的组织和管理更加清晰和高效。
一个模块就是一个独立的 JavaScript 文件。模块内的变量、函数、类等默认是私有的,只有通过 export 关键字导出的部分才能被其他模块使用。
// 导出单个变量或函数
export const num = 42;
export function add(a, b) {
return a + b
}
// 也可以将多个导出写在一处
const str = "Hello";
function subtract(a, b) {
return a - b;
}
export { str, subtract };
//对应页面导入
import { num, add } from "./module1";
常见的数据类型
字符串
String
数字
Number
数组
Array
布尔值
true和false。
null
null类型的默认值是null,从逻辑角度讲,是表示一个空对象指针
对象
Object
函数
function
未定义(Undefined)
声明了变量,但是没有初始化
日期
new Data()
Symbol
Symbol 类型本质上是一种唯一标识符,可用作对象的唯一属性名。