目录
其实最主要的主要是:
全局变量不会自动回收,只会在页面关闭的时候回收,所以要少使用全局变量;
局部变量会自动回收,使用完就会自动回收了
实时的计算内存的引用次数,当其变为0时就销毁内存
但是有缺点:嵌套引用会造成内存泄漏的问题:
- function fn(){
- let o1 = {}
- let o2 = {};
- o1.a = o2;
- o2.a = o1
- }
-
- fn();
代码结束时,o2 o1都有被引用次数,所以使用引用计数不会销毁内存。所以现在的浏览器大多不采用这种方法。
例如:
- function fn(){
- let a = 1;
- function f2(){
- console.log(a);
- }
- f2()
- }
- fn()
内层函数 f2 调用了外层函数变量 a 吗,这是最简单的写法
最基础的写法为:
闭包的最大作用是外部可以访问函数内部的变量!!
- function fn(){
- let a = 1;
- function f2(){
- return a
- }
- return f2
- }
- let sw = fn()()
- console.log(sw)//1
也就是说函数fn的返回值为f2函数,所以fn()==f2,fn()()==f2()从而使得外部可以访问a
应 用:使用变量a表示函数f2被调用的次数:
- function fn(){
- let a = 0;
- function f2(){
- a++
- console.log(a);
- }
- return f2
- }
- let sw = fn()
- sw()
这样的好处是,a是函数内部的变量,外部不能直接修改这个值,只能通过f2得到,实现了数据私有
这是js中的一种‘缺陷’,允许在变量声明之前被访问(存在于var)
比如:
- console.log(num+'个');
- var num = 10
结果为undefined个
其本质为:
- var num
- console.log(num+'个');
- num = 10
把所有的var声明的变量提升到当前作用域的最前面,但是只提升声明,不提升幅值
let const没有变量提升的问题
需求:求不定数量的数的和:
- function add(){
- let sum = 0;
- for(let i = 0;i<arguments.length;i++){
- sum+=arguments[i];
- }
- console.log(sum);
- }
- add(2,3,4,5,9)
arguments就称为动态参数,将输入看成一个数组 (伪数组,不能用pop push等操作)
第二种方法:
- function add(...args){
- let sum = 0;
- console.log(args);
- for(let i = 0;i
length;i++){ - sum+=args[i];
- }
- console.log(sum);
- }
- add(2,3,4,5,9)
...args就为剩余参数,也是将输入看成一个数组(真数组,可以使用pop等操作) ,但是其优点在于可以提取剩余变量,例如刚刚的那个例子,我再加一个需求:最少有两个参数:
- function add(a,...args){
- let sum = 0;
- console.log(args);
- for(let i = 0;i
length;i++){ - sum+=args[i];
- }
- console.log(sum);
- }
- add(2,3,4,5,9)
这样的话,会把2给a ,【3,4,5,9】给agrs,需要注意的是...args只能放最后。
作用:把数组展开:
- const arr = [2,3,4,6];
- console.log(...arr);//2 3 4 6
经典应用为,得到数组的最大值(因为数组是不能直接使用math.max的):
- const arr = [2,3,4,6];
- console.log(Math.max(...arr));//6
或者,合并数组:
- const arr = [2,3,4,6];
- console.log([3,4,...arr,99]);//[3, 4, 2, 3, 4, 6, 99]
主要作用是 使得代码更简洁,且改变this的指向
基本形式:
- const fn = (x)=>{
- console.log(x);
- }
-
- fn(3)//3
如果只有一个形参,可以忽略小括号:
-
- const fn = x=>{
- console.log(x);
- }
-
- fn(3)//3
当函数只有一行代码时 可以省略大括号:
- const fn = x=>console.log(x);
-
- fn(3)//3
如果是一行代码 且是return,可以省略:
- const fn = x=>x+x;
- console.log(fn(3));//6
箭头函数没有arguments,只有...args:
- const fn = (...args)=>{
- let sum = 0;
- for(let i = 0;i
length;i++){ - sum+=args[i];
- }
- return sum
- }
-
- console.log(fn(3,4,5,7));//19
一般来说,this是谁调用函数 ,this指向谁
但是箭头函数不会创造自己的this,而是从自己作用域的上一层沿用this,这个地方this是静态的,是函数声明时所在作用域下的this值
- let btn = document.querySelector('button');
- btn.addEventListener('click',function(){
- console.log(this);//btn
- })
-
- btn.addEventListener('click',()=>{
- console.log(this);//window
- })
第一个的this 指向调用者btn
第二个this 指向的是箭头函数声明时的作用域,也就是上一个作用域,既window
经典应用:需求是点击一个方块 一秒后背景颜色变红
- let divs = document.querySelector('.box')
-
- divs.addEventListener('click',function(){
- setTimeout(()=>{
- this.style.backgroundColor = 'red' //这个this还是指向divs
- },1000)
-
- })
但是如果setTimeout里面的函数还是用function,那么this指向的是window,因为是window调用了setTimeout
数组解构是将数组的单元值快速批量赋值给变量的方法
- const arr = [123,22,33]
- const[max,min,avr] = arr;
- console.log(max);//123
应用:变量值交换
- let a = 1;
- let b = 2;
- [a,b]=[b,a]
- console.log(a);//2
- console.log(b);//1
变量多 单元值少的情况
- const[a,b,c,d] = [1,2,3]
- console.log(a,b,c,d);//1 2 3 undefined
变量少 单元值多的情况
- const[a,b] = [1,2,3]
- console.log(a,b);//1 2
- const person = {
- name :'aa',
- age:17
- }
-
- const{name,age} = person;
- console.log(name);//aa
- console.log(age);//17
可以改名:
- const person = {
- name :'aa',
- age:17
- }
-
- const{name:username,age} = person;
- console.log(username);//aa
- console.log(age);//17
多重对象解构:
- const pig = {
- name: 'aa',
- family:{
- mom :'bb',
- papa:'cc',
- sist:'dd'
- },
- age:18
- }
-
- const {name,family:{mom,papa,sist}}=pig;
- console.log(mom);//bb
- const arr = [11,22,33];
- arr.forEach(function(item,index){
- console.log(item);
- console.log(index);
- })
结果为:11 0 22 1 33 2
item必须要写 index可以不写
贴一个小案例 可以看一下
- html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>商品渲染title>
- <style>
- * {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- }
-
- .list {
- width: 990px;
- margin: 0 auto;
- display: flex;
- flex-wrap: wrap;
- }
-
- .item {
- width: 240px;
- margin-left: 10px;
- padding: 20px 30px;
- transition: all .5s;
- margin-bottom: 20px;
- }
-
- .item:nth-child(4n) {
- margin-left: 0;
- }
-
- .item:hover {
- box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
- transform: translate3d(0, -4px, 0);
- cursor: pointer;
- }
-
- .item img {
- width: 100%;
- }
-
- .item .name {
- font-size: 18px;
- margin-bottom: 10px;
- color: #666;
- }
-
- .item .price {
- font-size: 22px;
- color: firebrick;
- }
-
- .item .price::before {
- content: "¥";
- font-size: 14px;
- }
-
- .filter {
- display: flex;
- width: 990px;
- margin: 0 auto;
- padding: 50px 30px;
- }
-
- .filter a {
- padding: 10px 20px;
- background: #f5f5f5;
- color: #666;
- text-decoration: none;
- margin-right: 20px;
- }
-
- .filter a:active,
- .filter a:focus {
- background: #05943c;
- color: #fff;
- }
- style>
- head>
-
- <body>
- <div class="filter">
- <a data-index="1" href="javascript:;">0-100元a>
- <a data-index="2" href="javascript:;">100-300元a>
- <a data-index="3" href="javascript:;">300元以上a>
- <a href="javascript:;">全部区间a>
- div>
- <div class="list">
-
- div>
- <script>
- const goodsList = [
- {
- id: '4001172',
- name: '称心如意手摇咖啡磨豆机咖啡豆研磨机',
- price: '289.00',
- picture: 'https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg',
- },
- {
- id: '4001594',
- name: '日式黑陶功夫茶组双侧把茶具礼盒装',
- price: '288.00',
- picture: 'https://yanxuan-item.nosdn.127.net/3346b7b92f9563c7a7e24c7ead883f18.jpg',
- },
- {
- id: '4001009',
- name: '竹制干泡茶盘正方形沥水茶台品茶盘',
- price: '109.00',
- picture: 'https://yanxuan-item.nosdn.127.net/2d942d6bc94f1e230763e1a5a3b379e1.png',
- },
- {
- id: '4001874',
- name: '古法温酒汝瓷酒具套装白酒杯莲花温酒器',
- price: '488.00',
- picture: 'https://yanxuan-item.nosdn.127.net/44e51622800e4fceb6bee8e616da85fd.png',
- },
- {
- id: '4001649',
- name: '大师监制龙泉青瓷茶叶罐',
- price: '139.00',
- picture: 'https://yanxuan-item.nosdn.127.net/4356c9fc150753775fe56b465314f1eb.png',
- },
- {
- id: '3997185',
- name: '与众不同的口感汝瓷白酒杯套组1壶4杯',
- price: '108.00',
- picture: 'https://yanxuan-item.nosdn.127.net/8e21c794dfd3a4e8573273ddae50bce2.jpg',
- },
- {
- id: '3997403',
- name: '手工吹制更厚实白酒杯壶套装6壶6杯',
- price: '99.00',
- picture: 'https://yanxuan-item.nosdn.127.net/af2371a65f60bce152a61fc22745ff3f.jpg',
- },
- {
- id: '3998274',
- name: '德国百年工艺高端水晶玻璃红酒杯2支装',
- price: '139.00',
- picture: 'https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg',
- },
- ]
-
-
-
-
- let list = document.querySelector('.list');
-
- function get(arr) {
- let str = ``
- arr.forEach((item, index) => {
- let { id, name, price, picture } = item;
- str += `${id}>
- ${picture} alt="">
-
${name}
-
${price}
- `
- });
- list.innerHTML = str;
- }
-
- get(goodsList)
-
- let filter = document.querySelector('.filter').querySelectorAll('a');
- for(let i=0;i
length;i++){ - filter[i].addEventListener('click',function(){
-
-
- if(this.getAttribute('data-index')==1){
- arr = goodsList.filter(item => item.price > 0 && item.price <= 100)
- }
- else if(this.getAttribute('data-index')==2){
- arr = goodsList.filter(item => item.price > 100 && item.price <= 300)
-
- }
- else if(this.getAttribute('data-index')==3){
- arr = goodsList.filter(item => item.price > 300)
-
- }
- else{
- arr = goodsList;
- }
- get(arr)
-
- })
- }
-
-
-
-
-
- script>
- body>
-
- html>
需要使用constructor函数来声明参数
- class fa{
- constructor(x,y){
- this.x = x;
- this.y = y;
- }
- sum(){
- console.log(this.x+this.y);
- }
- }
-
-
- let a = new fa()
利用extends
- class fa{
- constructor(x,y){
- this.x = x;
- this.y = y;
- }
- sum(){
- console.log('hhhh');
- }
- }
-
-
- class son extends fa{}
- let b = new son()
- b.sum()//hhhh
如果想将子类的参数传到父类并调用父类的函数,需要使用super方法,主要就是可以将子类的参数传给父类
- class fa{
- constructor(x,y){
- this.x = x;
- this.y = y;
- }
- sum(){
- console.log(this.x + this.y);;
- }
- }
-
- class son extends fa{
- constructor(x,y){
- super(x,y)
-
- }
-
- }
-
-
-
- let a = new son(7,4)
- a.sum()//11
如果子类本身也有参数和函数,也可以声明super,但是需要注意的是,super必须在this之前
- class fa{
- constructor(x,y){
- this.x = x;
- this.y = y;
- }
- sum(){
- console.log(this.x + this.y);
- }
- }
-
- class son extends fa{
- constructor(x,y){
- super(x,y)
- this.x = x;
- this.y = y;
- }
- jian(){
- console.log(this.x - this.y);
- }
- }
-
- let a = new son(7,4)
- a.jian()//3
- a.sum()//11