跳到主要内容

· 阅读需 7 分钟
DK

函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性就是计算机科学文献中称的 “闭包”。这个术语非常古老,是指函数变量可以被隐藏于作用链之内,因此看起来是和函数将变量“包裹”起来。

在 JavaScript 中,只有函数内部的局部变量不能直接访问到,而函数中的子函数能读取局部变量,因此可以把闭包简单理解成 "定义在一个函数内部的函数"

《JS 高级程序设计》里面的定义是:一个可以访问另一个函数里局部变量的函数既闭包。

阮一峰的网络日志:在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁

闭包是一种形式,它是以函数的方式表现出来。

用处:

  • 能读取其他函数内部变量的函数,并且是 「间接」访问,不能「直接」访问。
  • 让这些变量的值始终保持在内存中。

特点:

  • 可以记录诞生他的环境(全局环境是必有的),JS 也采用词法作用域,也就是说,函数的执行依赖于变量作用域,这个 作用域是在函数定义时决定的,而不是调用时决定的。
  • 闭包是把需要的变量保存到内置属性[[Scopeds]]上,这是一个数组,默认必有一个全局环境变量。其实就是帮我们把变量重新声明在当前的作用域中。(网上看的一些知识,自己也不太懂,逼格太高)

形成闭包的三个条件:

  1. 函数嵌套(有一个函数 A , 在函数 A 内部返回一个函数 B
  2. 访问所在的作用域的父级作用域 (在函数 B 中访问函数 A 的私有作用域变量
  3. 在所在的作用域外被调用 (在函数 A 外部,有变量引用函数 B
function A() {
var num = 100;
return function B() {
// 返回值函数B
var num1 = num; // 在函数B中访问函数A的局部变量
console.log(num1);
return num1;
};
}
var fn1 = A(); // 此处调用函数A,执行的结果就是函数B
var fn2 = fn1(); // 此处调用函数fn1(),执行结果就是引用函数B

使用闭包的注意点:

闭包会使得函数中的变量都被保存在内存中每个父函数调用完,就会形成新的闭包。父函数中的变量始终会在内存中,相当于缓存内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,尤其是IE 在我们使用完闭包之后,依然回收不了闭包里面引用的变量。

但是我认为: 使用了闭包那里面的变量明明就是我们需要的变量。不能说是内存泄漏,内存泄露是指: 你用不到(访问不到)的变量,依然占居着内存空间,不能被再次利用起来。

IE 内存泄漏的解决方法:在退出函数之前,将不使用的局部变量全部删除。大部分浏览器,通过赋值为 null,释放内存。在 IE 中 在 return 返回值下面 delete 变量。

闭包可以在父函数外部,改变父函数内部变量的值。 所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,因为都在内存中,所以不要随便改变父函数内部变量的值,否则一处变其它地方也会随之变化

个人理解:

其实我觉得,根本不需要知道闭包这个概念,一样可以使用闭包!

因为函数也是一个 var,只是它比较特殊,函数里面的 var 不能被外接直接访问,然后在函数里面定义了一个函数来访问。其实跟调用一个对象里面定义的函数然后访问对象里面 key,区别就是对象里面的一个 key 可以被外面显示调用(造成不能隐蔽的问题),闭包解决这个问题

闭包是 JS 函数作用域的副产品。

由于 JS 的函数内部可以使用函数外部的变量,正好符合了闭包的定义,而不是 JS 故意要使用闭包。

总结

闭包让程序更加安全,封装数据、暂存变量。不让外部直接访问到我们的数据。

· 阅读需 7 分钟
DK

函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性就是计算机科学文献中称的 “闭包”。这个术语非常古老,是指函数变量可以被隐藏于作用链之内,因此看起来是和函数将变量“包裹”起来。

在 JavaScript 中,只有函数内部的局部变量不能直接访问到,而函数中的子函数能读取局部变量,因此可以把闭包简单理解成 "定义在一个函数内部的函数"

《JS 高级程序设计》里面的定义是:一个可以访问另一个函数里局部变量的函数既闭包。

阮一峰的网络日志:在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁

闭包是一种形式,它是以函数的方式表现出来。

用处:

  • 能读取其他函数内部变量的函数,并且是 「间接」访问,不能「直接」访问。
  • 让这些变量的值始终保持在内存中。

特点:

  • 可以记录诞生他的环境(全局环境是必有的),JS 也采用词法作用域,也就是说,函数的执行依赖于变量作用域,这个 作用域是在函数定义时决定的,而不是调用时决定的。
  • 闭包是把需要的变量保存到内置属性[[Scopeds]]上,这是一个数组,默认必有一个全局环境变量。其实就是帮我们把变量重新声明在当前的作用域中。(网上看的一些知识,自己也不太懂,逼格太高)

形成闭包的三个条件:

  1. 函数嵌套(有一个函数 A , 在函数 A 内部返回一个函数 B
  2. 访问所在的作用域的父级作用域 (在函数 B 中访问函数 A 的私有作用域变量
  3. 在所在的作用域外被调用 (在函数 A 外部,有变量引用函数 B
function A() {
var num = 100;
return function B() {
// 返回值函数B
var num1 = num; // 在函数B中访问函数A的局部变量
console.log(num1);
return num1;
};
}
var fn1 = A(); // 此处调用函数A,执行的结果就是函数B
var fn2 = fn1(); // 此处调用函数fn1(),执行结果就是引用函数B

使用闭包的注意点:

闭包会使得函数中的变量都被保存在内存中每个父函数调用完,就会形成新的闭包。父函数中的变量始终会在内存中,相当于缓存内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,尤其是IE 在我们使用完闭包之后,依然回收不了闭包里面引用的变量。

但是我认为: 使用了闭包那里面的变量明明就是我们需要的变量。不能说是内存泄漏,内存泄露是指: 你用不到(访问不到)的变量,依然占居着内存空间,不能被再次利用起来。

IE 内存泄漏的解决方法:在退出函数之前,将不使用的局部变量全部删除。大部分浏览器,通过赋值为 null,释放内存。在 IE 中 在 return 返回值下面 delete 变量。

闭包可以在父函数外部,改变父函数内部变量的值。 所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,因为都在内存中,所以不要随便改变父函数内部变量的值,否则一处变其它地方也会随之变化

个人理解:

其实我觉得,根本不需要知道闭包这个概念,一样可以使用闭包!

因为函数也是一个 var,只是它比较特殊,函数里面的 var 不能被外接直接访问,然后在函数里面定义了一个函数来访问。其实跟调用一个对象里面定义的函数然后访问对象里面 key,区别就是对象里面的一个 key 可以被外面显示调用(造成不能隐蔽的问题),闭包解决这个问题

闭包是 JS 函数作用域的副产品。

由于 JS 的函数内部可以使用函数外部的变量,正好符合了闭包的定义,而不是 JS 故意要使用闭包。

总结

闭包让程序更加安全,封装数据、暂存变量。不让外部直接访问到我们的数据。

· 阅读需 2 分钟
DK

1、for循环

const arr1 = new Array(100);

for(var i=0;i<arr1.length;i++){
arr1[i] = i;
}

console.log(arr1);

// 生成0-99的数组

2、push方法

const arr2 = new Array();

for(let i=0; i < 100; i++){
arr2.push(i);
}

console.log(arr2);

3、while

· 阅读需 2 分钟
DK

颜色函数

  • rgb():RGB色彩模式
  • rgba():RGBA色彩模式
  • hsl():HSL色彩模式
  • hsla():HSLA色彩模式
  • color():色彩模式,基于当前颜色衍生出其他颜色

属性函数

  • attr():属性
  • var():变量

数学函数

· 阅读需 4 分钟
DK

需求背景

用户退出当前页面时,修改的数据未进行保存,需要发送接口请求实现自动保存的功能。简单分析需求可知,退出页面包含 路由切换关闭浏览器标签页两种情况:

  • 路由切换:项目使用 Vue2 开发,离开页面时可以在 beforeDestroy 钩子函数中调用接口实现保存数据,但是这个方法只能在路由切换当前组件销毁前触发,无法监听到浏览器页面关闭的情况。
  • 关闭浏览器标签页:考虑在 window.onunload 钩子函数中发送请求。

· 阅读需 1 分钟
DK

在 Git 中,有两个「偏移符号」: ^~

一、^ 的用法:

commit 的后面加一个或多个 ^ 号,可以 把 commit 往回偏移,偏移的数量是 ^ 的数量。例 如: master^ 表示 master 指向的 commit 之前的那 个 commit; HEAD^^ 表示 HEAD 所指向的 commit 往 前数两个 commit

· 阅读需 3 分钟
DK

首先需要明白,盒子模型主要定义四个区域:内容(content)、边框与内容的区域,称为内边距(padding)、边框(border)、边框与外部的区域,称为外边距(margin)。

区别

· 阅读需 3 分钟
DK

useReducer 接收两个参数:

第一个参数:reducer 函数,没错就是我们上一篇文章介绍的。第二个参数:初始化的 state。返回值为最新的 state 和 dispatch 函数(用来触发 reducer 函数,计算对应的 state)。按照官方的说法:对于复杂的 state 操作逻辑,嵌套的 state 的对象,推荐使用 useReducer。

听起来比较抽象,我们先看一个简单的例子:

· 阅读需 1 分钟
DK

设置内容显示多少行,多余的内容添加省略号

.ellipsis {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;

/ / moz 不设置也可以 display:-moz-box;
-moz-box-orient: vertical;
-moz-line-clamp: 1;
}