2018W23 学习笔记

这周因为朋友结婚帮忙的缘故,学习的内容明显下降了不少。所以,等明天开始,得需要恢复之前每天学习的强度。

本周的学习共分为3块:

  1. ES6基础学习与深入;
  2. Vue源码阅读;
  3. 前端进阶班的预习;
    下面我们按照上面模块一起去看一下本周我到底获得了哪些收货。

1.ES6学习

阅读完成《深入理解ES6》的第三章。第三章主要讲述的是函数的ES6新特性。
我们都知道ES6是ES5的加强与补充,是为了解决ES5中某些遗留问题而提出的新的解决方案或者加强,所以顺着这个思路,我就去做了这样的笔记。

1.1 ES6函数新特性

在ES6中,针对函数,补充了如下的一些特性:

  • 参数默认值
  • 使用不具名函数
  • 函数构造器增强
  • 扩展运算符
  • 函数的双重用途
  • 块级函数
  • 箭头函数
  • 尾调用优化
1.1.1 参数默认值

传统的ES5设置函数默认值需要逐个对参数进行设置,所以代码量非常多,而且对于JS这种不限制函数参数的行为其扩展性也很差。所以ES6在ES5的基础上增加了参数默认值的特效,其语法如下:

    function demo(url, timeout = 2000 , fn = function()
        {console.log('do it')
    })

值得注意的是,我们可以向参数传递Undefined值来使用默认的参数值,以上面函数为例,

      demo('http://www.baidu.com',undefined,fn)

这样就可以继续使用第二个参数的默认值了。

初次之外,还涉及到了2个比较“冷门的问题”:

  1. ES6参数默认值是如何影响argument对象;
  2. 参数默认值的暂时性死区;

1.1.2 使用不具名函数

ES5的不具名的arguments对象在实际使用过程中会有很多的限制。在书中,就通过underscorejs库中Pick函数的讲解来说出arguments的不足。

  // 复制特定对象的特定属性
  function pick(object) {
    let result = Object.create(null);
    // 从第二个参数开始处理
    for (let i = 1, len = arguments.length; i < len; i++) {
      result[arguments[i]] = object[arguments[i]];
  }
    return result;
  }

  1. 虽然该函数能处理多个函数,但是在函数的表现上则完全看不出;
  2. 函数的第一个参数是选中的目标对象,从第二个开始才是需要复制的属性。

因此ES6引入了剩余参数这个概念,使用剩余函数对上述函数进行改写,则清晰和优雅不少。

  function pick(object, ...keys) {
    let result = Object.create(null);
    for (let i = 0, len = keys.length; i < len; i++) {
    result[keys[i]] = object[keys[i]];
    }
    return result;
}

通过引入剩余参数,我们就可以知道函数可以处理多余的函数。并且这与包含所有参数的arguements不同,我们可以单独对剩余函数进行处理。当然剩余函数也有剩余的不足,主要有以下两点:

  1. 剩余参数必须要放在最后面;
  2. 剩余参数放在setter函数中不可用,会报语法错误。

1.1.3 函数构造器

作者声称,函数默认值加上剩余函数加强了函数构造器的能力,但是,在实际工作中,笔者觉得函数构造器的用处并不多。


1.2.4 扩展运算符

剩余参数是将多个参数添加进数组,而扩展运算符则是将数组的元素分成单个的元素,类似于split的功能。它主要的目的是代替apply。其使用场景如下:

   let values = [1,8,3];
  // ES5版本
  Math.max.apply(Math, values);

   // ES6版本
  Math.max(...values);

在之前的ES5版本中,要实现求一个数组的最大数,需要使用apply去更改上下文的执行环境,而有了扩展运算符之后,则轻松很多,并且从语义化角度上来说,也清晰不少。


1.1.4 函数的双重用途

在ES5中,函数是否调用new操作符则意味着不同的用途。没有new操作符,它就是执行函数体内的代码。而有了new,函数就会执行内部[[ constructor]]方法,构建一个对象。所以这就是函数的双重用途的意思。
在ES5中,判断函数是否调用了new操作,最简单也是最流行的一种做法就是使用instanceof这个方法,但是,这个方法也有明显的缺陷,开发者可以使用apply去改变函数执行的上下文顺序,从而使instanceof的执行判断出错。

function Person(name) {
    if (this instanceof Person) {
        this.name = name; // 使用 new
      } else {
          throw new Error("You must use new with Person.")
      }
     }  
      var person = new Person("Nicholas");
      var notAPerson = Person.call(person, "Michael"); // 奏效了!

因此在ES6中引入了new.target来弥补相关不足。

    function Person(name){
        if(typeof new.target != undefined){
            this.name =name;
        }else{
            throw new Error('must with new');
        }
    }

其底层原理是,在调用new 操作符时,调用[[ constructor ]]方法,new.target才会生成,(否则为undefined)并且将this对象赋值为原构造函数。


1.1.5 ES6箭头函数

之前也学习过ES6箭头函数,但是没有想到的是,ES6函数为了增强ES5函数的一些不足,竟然和传统的函数有很多不一样的特点:

  1. 没有this,super,arguments和new.target绑定;
  2. 箭头函数不能作为构造函数,也就是说不能被new,也没有prototype属性;
  3. 不能更改this的指向(js深恶痛绝的this指向问题);
  4. 不能重复相同的参数命名。

这些特点是为了减少箭头函数内部的错误与不确定性,为了js函数更好的运行。


2. Vue源码学习

主要是看了第500-900行的代码,粗略地知道了Vue对数组的监听。

首先获取数组的原型对象,在这个对象上有数组的方法。

    var arrProto = Array.prototype;

然后使用Object.create的方法创建了一个空对象,其中它的原型链上有数组方法的集合。

    var arrMethods = Object.create(arrProto);

创建一个数组方法的集合:

    var methodsToPatch = [
            'push',
            'pop',
            'shift',
            'unshift',
            'splice',
            'sort',
            'reverse'
        ];

最关键的一步:对arrMethods进行构建:

给arrMethods添加属性

  1. 遍历methodsToPatch,在回调函数中调用def函数给arrMethods添加方法相对应的属性
    methodsToPatch.forEach(method => {
            def(arrMethods, method, function mutator() {
                // 相关代码第二步进行解析
            })
        });

    function def(obj, key, val, enumerable) {
            Object.defineProperty(obj, key, {
                value: val,
                enumerable: !!enumerable,
                writable: true,
                configurable: true
            });
        }Ï

  1. muator函数的定义
       function mutator() {
            //定义args容器,并且获取函数参数的长度
            var args = [],
                len = arguments.length;

            while (len--) args[len] = arguments[len]; //将类数组转换成数组

            //这里的this指的就是arrMethods 调用arrMethods中的方法和参数
            var result = original.apply(this, args);

            //监听类 下面代码就调用了它的notify和observeArray方法
            var ob = this.__ob__; 
            var inserted;

            //如果是push/unshift/splice方法 对inserted进行赋值
            switch (method) {
                case 'push':
                case 'unshift':
                    inserted = args;
                    break;

                case 'splice':
                    inserted = args.splice(2);
                    break;
            }

            
            if (inserted) {
                ob.observeArray(inserted); //对传入的参数进行监听
            }

            ob.deep.notify(); //通知视图发生变化

            return result;

        };  
    

3.课程进阶学习

这里总结性的语言就不写了,抛出问题,测试一下是否能回答出:

  • 有哪3种为DOM元素注册事件处理函数的方式?分别有什么限制和优点?

  • Dom Event接口中哪些属性和接口需要了解?

  • 如何自定义一个Event事件?请写出一个demo;

  • JS事件的传播是如何传播的?

  • 简述下面代码的执行顺序

        // html 
        <div id='outter'>
            <p id='inner'> click </p>
        </div>

        // js
        
        let outter = document.getElementById('outter');
        let inner = document.getElementById('inner');
        
        outter.addEventListener('click', function () {
            console.log('outter-true')
        }, true);
        inner.addEventListener('click', function () {
            console.log('inner-true')
        }, true);
        inner.addEventListener('click', function () {
            console.log('inner-false')
        }, false);
        outter.addEventListener('click', function () {
            console.log('outter-false')
        }, false);

  • 请解释一下什么是JS事件代理?

  • 请简单地写一下事件代理的demo;

  • 可以使用哪个事件来阻止事件的传播?

  • util.callbackify这个API的作用是什么?

  • 回调函数中的第一个参数和第二个参数分别是什么?

  • 请写出API的具体使用方法:将一个异步函数转换为错误回调优先的函数

  • 回调函数中的 null 有什么意义么?

  • 回调函数中的错误原因可以通过什么属性获取?

  • generator对象是什么?怎样才能获取到?

  • 请写出generator最基本的语法;

  • 调用一个生成器函数会立即执行函数体里面的语句么?

  • 发布/订阅模式和观察者的区别是什么?


梳理完本周学习的内容,发现有很多都已经忘了,不多说了,需要赶紧去复习。

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

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,149评论 0 13
  • 三,字符串扩展 3.1 Unicode表示法 ES6 做出了改进,只要将码点放入大括号,就能正确解读该字符。有了这...
    eastbaby阅读 1,534评论 0 8
  • 函数和对象 1、函数 1.1 函数概述 函数对于任何一门语言来说都是核心的概念。通过函数可以封装任意多条语句,而且...
    道无虚阅读 4,564评论 0 5
  • 第3章 基本概念 3.1 语法 3.2 关键字和保留字 3.3 变量 3.4 数据类型 5种简单数据类型:Unde...
    RickCole阅读 5,126评论 0 21
  • 你可能觉得,“战略”这个词你已经非常熟悉了,很多地方都听过无数次。但是,在很多情况下我们对”战略“这个词的理解是很...
    余子祥阅读 283评论 0 1