JavaScript语言精粹学习总结

第一章 精华

Nothing :)

第二章 语法

  • JavaScript中,块注释/*...*/是不太安全的,因为正则表达中可能出现块注释的字符,下面代码会出现一个语法错误,所以建议使用行注释//
    /*
    var a=/a*/;
    console.log(a.test("aaa"));
    */
    
  • JavaScript中没有字符类型,表示字符是通过只包含一个字符的字符串来表示的。
  • 被当做是假(falsy)的:
    nullundefined、空字符串""、数字0、NaN
    除上面几个之外的所有值所有对象
  • 被当做是真的:throw语句在一个try代码块中抛出一个异常,控制流会跳转到catch从句中;如果在throw语句在函数中,则控制流跳转到调用该函数的try语句的catch从句中。

第三章 对象

  • 广义的对象有对象、数组、正则表达式、函数。
  • 属性的名字(key)是字符串,如果是合法标识符(JavaScript中合法标识符数字字母下划线$)且不是保留字那么不必非要在key两边加双引号
  • 对象的传递是按引用传递(即通过复制引用来传递,不违背JavaScript中函数的参数都是按值传递)
  • 每个对象都有原型,字面量创建的对象原型为Object.prototype,即
    var a={}
    a.__proto__===Object.prototype// true
    
  • 获取对象的某个属性值,没有的话会沿着原型链寻找,最终找到Object.prototype还找不到会返回undefined
  • for in遍历的顺序是不确定的
  • delete不会触及原型链中的对象
  • 最好把全局性的资源都纳入一个统一的全局变量的命名空间之下

第四章 函数

  • 函数也是对象,函数对象的原型为Function.prototype,该原型也不算普通的对象,也是一个函数,typeof Function.prototypefunction
    下面来看看面向对象(类)的代码风格中的实体与实体之间的关系:
    function Foo(who) {
        this.me = who;
    }
    Foo.prototype.identify = function() {
        return "I am " + this.me;
    };
    function Bar(who) {
        Foo.call( this, who );
    }
    Bar.prototype = Object.create( Foo.prototype );
    Bar.prototype.speak = function() {
        console.log( "Hello, " + this.identify() + "." );
    };
    var b1 = new Bar( "b1" );
    var b2 = new Bar( "b2" );
    b1.speak();
    b2.speak();
    
原型和原型链
  • JavaScript中的函数参数不会进行类型检查,任何类型的值都可以传进任何参数中。
  • this的绑定
    • this的隐式绑定也称为方法调用模式,就是函数以一个对象的方法的形式来调用(虽然并不是真正意义上的方法,与java中的不同),绑定到调用方法的对象上。
    • this的默认绑定也称为函数调用模式,就是直接调用,这时绑定到全局对象(非严格模式)或undefined上(严格模式)。这是一个语言设计上的错误,不过可以很容易解决,就是将this赋值给that(或者其他任何合法标识符)。
    • this的new绑定也称为构造器调用模式,就是通过new关键字来调用构造函数。
    • apply/call调用模式,也就是this的硬绑定,apply的第二个参数为数组,call的第二个参数为列表。
  • 可以给Function.prototype增加一个方法:
    Function.prototype.method=function(name,func){
        if(!this.prototype[name]){
            this.prototype[name]=func;
        }
        return this;
    }
    

这样以后给对象增加方法的时候可以直接调用,不用再写prototype这几个字符。
其实上面的最后返回一个this,是为了级联调用(级联见下面)。

  • 作用域和闭包参见《你不知道的JavaScript上卷》。
  • 如果在一个方法里返回this,就可以启用级联,在一个级联中,我们可以在单独一条语句中依次调用同一个对象的很多方法。例如,在一个启用级联的Ajax类库中可能允许我们以下面这样的形式去编码:
    getElement('myBoxDiv')
        .move(350,150)
        .width(100)
        .height(100);
    
  • 柯里化
    Function.method('curry',function(){
        var outterArgs=Array.prototype.slice.call(arguments),
            that=this;
        return function(){
            var innerArgs=Array.prototype.slice.call(arguments);
            return that.apply(null,outterArgs.concat(innerArgs));
        };
    });
    
    function add(a,b){
        return a+b;
    }
    var addCurry=add.curry(2);
    console.log(addCurry(3));//5
    
  • 记忆
    有时间重新看一下,语言精粹p.43

第五章 继承

  • 伪类模式(面向对象的模式)

    function Foo(who) {
        this.me = who;
    }
    Foo.prototype.identify = function() {
        return "I am " + this.me;
    };
    function Bar(who) {
        Foo.call( this, who );
    }
    Bar.prototype = Object.create( Foo.prototype );
    Bar.prototype.speak = function() {
        console.log( "Hello, " + this.identify() + "." );
    };
    var b1 = new Bar( "b1" );
    var b2 = new Bar( "b2" );
    b1.speak();
    b2.speak();
    
  • 委托模式(也称为差异化继承)

    var Foo = {
        init: function(who) {
            this.me = who;
        },
        identify: function() {
            return "I am " + this.me;
        }
    };
    var Bar = Object.create( Foo );
    Bar.speak = function() {
        console.log( "Hello, " + this.identify() + "." );
    };
    var b1 = Object.create( Bar );
    b1.init( "b1" );
    var b2 = Object.create( Bar );
    b2.init( "b2" );
    b1.speak();
    b2.speak();
    
  • 函数化模式:(为了解决伪类和委托模式中没有办法保存私有变量的问题),我们从构造一个生成对象的函数开始,(语言精粹建议以小写字母开头,因为不需要使用new前缀,但是为了和上面保持一致,感觉还是用首字母大写比较合适,这里我首字母大写,如果以后需要小写,改过来)。包括4个步骤:

    1. 创建一个新对象。
    2. 有选择地定义私有变量和方法
    3. 给这个新对象添加一些特权方法
    4. 返回这个对象

    说实话感觉和模块化差不多。

    function Foo(spec){
        var obj={};
        obj.identify=function(){
            return "I am "+spec.name;
        };
        return obj;
    }
    var foo1=Foo({name:"foo1"});
    
    function Bar(spec){
        var obj=Foo(spec);
        obj.speak=function(){
            console.log("Hello, "+obj.identify()+".");
        };
        return obj;
    }
    var bar1=Bar({name:"bar1"});
    var bar2=Bar({name:"bar2"});
    bar1.speak();
    bar2.speak();
    

    其中,spec对象包含构造器构造一个实例所需要的所有信息。

  • 部件
    没有看懂,语言精粹p.55

第六章 数组

  • 数组的length属性是没有上界的,设置更大的length不会分配更多的空间给数组,但是将length设小将导致所有下标大于length的值被删除。
  • 判断是否是数组时,最好用Object.toString.call(a)==="[object Array]"
  • 指定初始值
    可以很容易地自己实现一个函数来初始化:
    Array.dim=function(dimention,initial){
        var a=[],i;
        for(i=0;i<dimention;i++){
            a[i]=initial;
        }
        return a;
    }
    
     var myArr=Array.dim(10,0);//创建一个包含10个0的数组。
    

第七章 正则表达式

  • 在JavaScript中,正则表达式必需写在一行中,无论多长

  • 一个正则表达式序列由正则表达式因子和(可选的)量词组成,每个因子可以选择是否跟随一个量词,这个量词决定了这个因子被允许出现的次数。

  • 正则表达式因子
    正则表达式可以是一个字符、一个组(由圆括号包围的组)、一个字符类(由方括号包围)或者一个转义序列(如\n\d等)。

    • 字符

      除了控制字符(\ / [ ] ( ) { } ? + * | . ^ $),其他所有字符均会按照字面处理。

    • 正则表达式分组

      正则表达式分组有四种:

      • 捕获型分组
        一个正则表达式分组是一个包含在圆括号里的正则表达式分支,任何匹配这个分组的字符都会被捕获,第一个分组是1,第二个分组是2,以此类推。
      • 非捕获型分组
        非捕获型分组就是(?: )包围的分组,只会对字符进行简单的匹配,但是不会捕获所匹配的文本,不会干扰捕获型分组的编号,有微弱的性能优势。
      • 向前正向匹配
        包围在(?= )中的分组,类似于非捕获型分组,在在这个组匹配后,文本会倒回到它开始的地方,实际上并不匹配任何东西,不是一个好特性。
      • 向后负向匹配
        包围在(?! )中的分组,类似于向前正向匹配,但只有在它匹配失败时才会继续向前进行匹配,不是一个好特性。
    • 正则表达式字符类(字符集)

      正则表达式字符类是一种指定一组字符的便利方式,用[]包围起来,内部可以包含任意字符(除了/ \ [ ] - ^这几个字符),如果要包含上述几个字符,需要转义(此处的转义为字符转义)

      正则表达式字符类

      之所以排除这几个字符是因为,/会被当做正则表达式结束标志,需要转义;\本身用作转义字符标志,需要转义;[]是包围字符类的符号,需要转义;-表示一个范围,比如[a-z]表示小写字母a到z,所以需要转义;^表示取反,即如果[之后的第一个字符是^,那么这个类就会排除这些特殊字符,如[^abc]会匹配除了a,b,c之外的所有字符。

    • 正则表达式转义序列

      正则表达式因子的转义和字符串或者字符类中的转义稍有不同。正则转义序列由:

      • \n换行符
      • \r回车符
      • \f换页符
      • \t制表(tab)符
      • \d等同于[0-9],匹配一个数字,/D表示与其相反的[^0-9]
      • \w等同于[0-9A-Z_a-z]\W表示与其相反的[^0-9A-Z_a-z]
      • \s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]
      • \S匹配任何非空白字符。等价于 [^ \f\n\r\t\v]
      • \1是指向分组1所捕获到的文本的一个引用,所以它能够被再次匹配,\2是指向分组的2的引用,以此类推
  • 正则表达式量词
    正则表达式量词可以跟在正则表达式因子后面表示这个因子被匹配的次数。

    • 包围在一对花括号中的一个数字表示这个因子应该被匹配的次数,如/www/等同于/w{3}/{3,6}会匹配3到6次(3、4、5或者6次),{3,}会匹配3次或更多。
    • ?表示0或1次,等同于{0,1}
    • *表示0或多次,等同于{0,}
    • +表示1或多次,等同于{1,}

    如果只有一个量词,表示趋向于进行贪婪性匹配,即匹配尽可能多的副本直到达到上限;如果这个量词后面附加一个后缀则表示趋向于进行非贪婪性匹配,即只匹

    QQ图片20181014123347.png

    配必要的副本就好。一般情况下最好坚持使用贪婪性匹配

    下面来看一个实例,匹配URL的正则表达式。


    1
2
3
4

以上便是正则表达式parse_url的所有因子。

5

第八章 方法

  • Array
    • concat
      不修改原数组,产生一个新数组,返回生成后的新数组。
    • join
      join方法用一个seperator分隔符将数字元素连接起成一个字符串,默认的seperator,join连接字符串没有+运算符快。返回字符串。
    • push
      改变原数组,返回新数组长度。
    • pop
      改变原数组,返回被移除的元素。
    • shift
      改变原数组,返回被移除的元素。
    • unshift
      改变原数组,返回新数组的长度。
    • reverse
      改变数组,将数组反向,返回反向后的数组。
    • slice
      不改变原数组,返回切割后的数组(或者说是原数组的一段浅复制)。
    • splice
      改变原数组,返回包含被移除元素的数组。从第一个参数的位置,删除第二个参数个数的元素,插入第三个元素(以及第四个第五个元素...)。
    • sort
      改变原数组,将原数组进行排序。
      注意,sort方法是不稳定的,排序的稳定性指的是排序后数组中的相等值的相对位置没有发生变化,而不稳定性排序则会改变相等值的相对位置
  • Number
    • toString
      转换为字符串。
    • toFixed
      保留指定小数位数的小数。
    • toPrecision
      保留指定整个数字位数的小数。
  • Object
  • RegExp
    • exec
      正则表达式最强大(和最慢)的方法,详见语言精粹p.86
    • test
      正则表达式最简单(和最快)的方法,详见语言精粹p.88
  • String
    • charAt
      返回指定位置的单个字符的字符串。
    • charCodeAt
    • concat
      连接,很少被使用,因为+更方便
    • indexOf
    • lastIndexOf
    • match
    • replace
    • slice
      复制字符串的一部分,substring也具有这种功能,但不要使用substring,使用slice就行。
    • split
    • toLowerCase
    • toUpperCase
    • fromCharCode

第九章 代码风格

  • 缩进4个空格
  • if(之间加个空格,让if看起来不会像一个函数调用
  • 在除了.[之外的所有中置运算符两边加个空格
  • 每个逗号和冒号后面加一个空格
  • 在诸如ifwhile这样的结构化语句中,始终使用代码块{}
  • {放在一行的结尾而不是下一行的开头
  • 写有用的注释
  • 在其他语言中,变量在它们第一次被使用时声明是个好习惯,在JavaScript中却不是个好建议,因为JavaScript没有块作用域,最好在每个函数最好是就声明所有用到的变量。

第十章 优美的特性

emmm,没啥好像

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

推荐阅读更多精彩内容