JavaScript笔记-4

作用域

  • 作用域决定了变量、常量和参数被定义的时间和位置
  • 形参只有在函数被调用的时候才变成实参,函数返回后参数就失去作用域
  • 变量和常量只有在创建后才存在,使用let、const声明前,他们是没有作用域的
  • var

作用域和存在

  • 作用域

    • 当前可见并且可被正在执行的代码块访问的标识符

    存在

    • 保存了已经分配过内存的数据的标识符

静态作用域与动态作用域

JavaScript中,作用域是静态的

  • 静态作用域
    • 在某个作用域内定义函数,该作用域包含的所有变量也在该函数的作用域内。
    • 静态作用域适用于全局作用域、块作用域、函数作用域。

全局作用域

全局作用域中声明的一切在所有作用域中都可用,所以要谨慎使用全局变量

块作用域

Let 和 const 声明的变量名处在块作用域中

变量屏蔽

独立外部块的同名变量,屏蔽了外部块定义的变量

const obj = {
        color: 'red'
      },
      objCopy = obj,
      number = 100;

function fun() {
    const number = '一百';

    console.log(number);
    objCopy.color = '红色';
}

fun(); //一百
console.log(number); //100
console.log(obj); //{color: "红色"}
console.log(objCopy); //{color: "红色"}

函数、闭包和静态作用域

  • 闭包

    故意将函数定义咋一个指定的作用域中,并明确地指出它对该作用域具备访问权限

    let fun ;
    {
        fun = function(){
              console.log(color) ;
        } ;
        const color = 'red' ;
    }
    fun() ;
    

    闭包内定义的函数还允许访问一些正常情况下无法访问到的信息。

    let fun; 
    {
        const list = {};
    
        fun = function (name) {
              return list;
        };
    }
    
    const newList = fun();
    newList.color = 'pink' ;
    
    console.log(newList) ;//{color: "pink"}
    console.log(fun()) ;//{color: "pink"}
    console.log(list) ;//list is not defined
    

即时调用函数表达式

(function(){
    
    //代码
  
}) () ;

好处是,任何内部信息都有自己的作用域,并且因为它本身就是函数,它可以向作用域外传递信息。

  • 即时调用函数作用域内,变量是安全的,外部不能访问它。

  • 可以从即时调用函数返回任何想要的结果,笔记常见返回数组、对象、函数。

  • 可以打印出自己被调用的次数,而且不会被篡改

    const message = (function () {
    
          let sum = 0;
          const str = '又大又宽又圆';
    
          return function () {
    
                console.log(`信息的长度是${str.length}, \n` +
    `你是第${++sum}获得提示的人。`);
            
          } ;
    
    })();
    
    message() ;//信息的长度是6, 
                       //你是第1获得提示的人。
    message() ;//信息的长度是6, 
                       //你是第2获得提示的人。
    message() ;//信息的长度是6, 
                       //你是第3获得提示的人。
    

函数作用域和提升

var 声明的变量,可在当前作用域的任意地方可用,甚至可以在声明前使用

任何使用var声明的变量都会被提升到作用域顶部,提升不是赋值。

/*
 *JavaScript解释下面代码的方式:
 *  
 *  var a ;
 *  var y ;
 *  console.log('第一次打印a :'+a) ;
 *  if(a !== 0){
 *      console.log('第一次打印b :'+b) ;
 *
 *      b = 1 ;
 *
 *        if(b){ a = 0 ;}
 * 
 *      console.log('第二次打印b :'+b) ;
 *  }
 * 
 *  if(a === 0) console.log('第三次打印b :'+b) ;
 */

console.log('第一次打印a :'+a) ;

if(a !== 0){
    console.log('第一次打印b :'+b) ;

    var b = 1 ;

    if(b){ var a = 0 ;}

    console.log('第二次打印b :'+b) ;
}

if(a === 0) console.log('第三次打印b :'+b) ;

同一函数或全局作用域内,var不能用来创建新的变量,变量屏蔽现象也不会出现

//使用var后,变量屏蔽现象不会出现
var number = 1000 ;
if(number === 1000){
    var number = 999 ;
    console.log(number) ;//999
}
console.log(number) ;//999

//使用let
let number = 1000 ;
if(number === 1000){
    let number = 999 ;
    console.log(number) ;//999
}
console.log(number) ;//1000

函数提升

函数声明也会被提升至他们作用域的顶部

临时死区

在ES6中没有必要使用typeof来检查变量是否被定义

严格模式

代码第一行插入字符串"use strict"

  • 不建议在全局作用域使用严格模式,它会应用于所有代码,多人协作合并代码容易出错
  • 建议在单独函数中开启严格模式,或者将所有代码封装在一个立即执行的函数中。

数组

操作数组

  • 会修改原数组*

    方法 描述
    .push() 数组最后添加元素,return新数组长度
    .pop() 数组最后删除元素,return被删除的元素
    .shift() 删除数组第一个元素,return被删除的元素
    .unshift() 添加数组第一个元素,return返回新数组长度
    .reverse() 颠倒当前数组得顺序
    .sort() 对当前数组进行排序,接受一排序函数作为参数
    ES6新方法 描述
    .copyWithin 将数组中一段元素复制到数组得另一个位置,
    并覆盖此位置的原来元素,
    第一个参数 复制到哪
    第二个参数 从哪里开始复制
    (可选)第三个参数 复制多少个参数
    .fill() 将一个固定值赋值给数组中任意位置元素
    const arr = [1, 2, 3, 4];
    console.log(arr) ;//[1, 2, 3, 4]
    arr.copyWithin(2, 1, 3) ;
    console.log(arr) ;//[1, 2, 2, 3]
    arr.fill('a', -2, -1) ;
    console.log(arr) ;//[1, 2, "a", 3]
    
  • 不会修改原数组,返回新数组

    方法 描述
    .concat() 给数组添加多个元素,return新数组
    .slice() 获取数组得子数组,return子数组
    .filter() 比较麻烦,执行百度
  • 不会修改原数组,返回其他

    方法 -
    .indexOf() 返回和查找的内容完全相同的第一个元素下标,没找到返回-1,第二参数接受起始下标
    .lastIndexOf() 返回和查找的内容完全相同的倒数第一个元素下标,没找到返回-1,第二参数接受起始下标
    .findIndex() 接受一个匹配函数作为参数,返回查找到的元素下标,否则返回-1
    .findLastIndex() 接受一个匹配函数作为参数,返回查找到的元素下标,否则返回-1
    .find() 返回查找到的第一个元素本身
    .reduce() 自行百度
    //reduce用法
    const arr = [1, 2, 3, 4] ;
    //(a, el)回调函数参数,a为累加起始值(此处为100),el数组元素
    const b = arr.reduce((a, el) => a+el , 100) ;
    console.log(b) ;//110
    
    
    //reduce 进阶用法
    const arr = [
                'Bosd',
                'Go98',
                'Ixj',
                'Eoo',
                'Ajv',
                'Clsq',
                'Avi',
                'Fk.x',
                'Cro2v',
                'D0we',
                'Ezxp',
                'G3io',
                'I-l'
            ] ;
            const newArr = arr.reduce((a, el) => {
                if(!a[ el[0] ]) a[ el[0] ] = [] ;
                a[el[0]].push(el) ;
                return a ;
            }, {}) ;
            console.log(newArr) ;
    
            /*        
                {
                    A: ["Ajv", "Avi"]
                    B: ["Bosd"]
                    C: ["Clsq", "Cro2v"]
                    D: ["D0we"]
                    E: ["Eoo", "Ezxp"]
                    F: ["Fk.x"]
                    G: ["Go98", "G3io"]
                    I: ["Ixj", "I-l"]
                }
            */
    
const arr = [
            1, 
            'a', 
            true, 
            {name: 'Tom'}, 
            null, 
            23, 
            'b', 
            {color: 'red'}, 
            false
        ] ;
        
const a = arr.find(
  (el, i) => i > 2 && typeof el === 'object'
) ;

console.log(arr) ;//[1, "a", true, {…}, null, 23, "b", {…}, false]
console.log(a) ;//{name: "Tom"}
  • 即修改原数组,也返回新数组

    方法 描述
    .splice() 第一个参数修改元素位置
    第二个参数删除元素个数
    其他参数是添加到数组得元素
    return被删除的元素

数组方法,已删除或者未定义的数组

当数组中的元素未被赋值或已被删除,map,filter,reduce就不会调用所传入的函数。

一般情况不会对数组使用delete,会造成数组缺口

字符串连接

Array.prototype.join()方法接受一个分隔符作为参数,返回一个连接了所有元素的字符串

const arr = [1, 'a', true, undefined, null, NaN, {}, '', [] ] ;
const a = arr.join('?') ;
console.log(a) ;//1?a?true???NaN?[object Object]??
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容