《JavaScript言语精炼 修订版》 读书笔记

之前看到这篇文章,
前端网老姚浅谈:怎样学JavaScript?,说到怎样进修JavaScript,那就是
看书、剖析源码。

10本书读2遍的长处,应当大于一本书读20遍。

看书主动进修,看视频是被动进修。

看书和剖析源码的机遇。但已事变一年半载时,恰是进步的好时刻,此时能够去看书了。周全体系的梳理学问点,扫清本身的盲区。假如只是靠项目履历是不够的,经由历程项目来进修,那>肯定是必需的,事变本身就是一个进修的历程。

怎样把一本书看完呢?很简朴,敲。笔墨加代码都敲。

比较认同老姚的说法。客岁毕业到现在,我也算是事变一年了,是时刻看书查缺补漏了。

因而我就先把这本薄的典范书《JavaScript言语精炼 修订版》豆瓣念书本书简介(统共10章,撤除附录,才100页),读完并记录了一些笔记。基础算是摘抄书本的,本身遐想到了一些学问和材料也扩大了一下。整体写下来近一万字。念书笔记还能够分享给他人看。回忆时,书不在身旁还能够看看本身的笔记。想一想这类典范书记一遍着手敲一遍也是很值得的。不过这念书笔记中能够会有一些错别字,浏览时假如发明迎接斧正。

第1章 英华

大多数言语都有英华和糟粕。JavaScript使人诡异的事变是,在对这门言语没有的太多相识,以至对编程都没有太多相识的情况下,你也能用它来完成事变。
看到这里不禁想起:

张鑫旭大牛在
《我对知乎前端相干题目标十问十答》

非盘算机专业背景进修JS要点有这一条:

一切继承和原型相干内容跳过,注重,是跳过,不要看!没有这些JS一样能够活得很好,你的一样平常事变一样玩得飞起,固然,你没忍住看了相干学问也没紧要,因为你会发明本身看不懂的;

JavaScript的函数是(主要)基于词法作用域的顶级对象。

译注:
JavaScript中的函数是依据词法来分别作用域的,而不是动态分别作用域的。具体内容拜见《
JavaScript威望指南》中译第5版相干章节“8.8.1 词法作用域”。

JavaScript有非常壮大的对象字面量示意法。这类示意法是JSON的灵感泉源。

原型继承是JavaScript中一个有争议的特性。

ECMAScript编程言语》第3版定义了JavaScript的规范。
ES3规范
扩大:颜海镜大牛整顿的ES3中文版
颜海镜大牛整顿的ES5中文版
W3c ES5中文版
阮一峰大牛的书本《ES6规范入门2》
更多内容可拜见这篇文章:ECMAScript 2018 规范导读

一个简朴的例子:

Function.prototype.method = function(name, func) {
  this.prototype[name] = func;
  return this;
}

书中坚持到底都邑用到这个method计划,作者将会在第4章诠释它。

第2章 语法

本章主要用铁路图(语法图)示意语法。
主要有:空缺、标识符、数字、字符串、语句、表达式、字面量、函数。
typeof 运算符发作的值有'number', 'string','boolean','undefined','function','object'。假如运算数是一个数组或许是null,那末效果是'object',这实际上是不对的。

第3章 对象

JavaScript简朴数据范例包括数字、字符串、布尔值,null值和undefined值。其他一切值都是对象。
数组、字符串和布尔值“貌似”对象,因为它们具有要领(包装对象),但它们是不可变的。
对象是属性的容器,个中每一个属性都具有名字和值。属性名能够是包括空字符串在内的一切字符串,属性值能够是除了undefined值之外的任何值。

JavaScript包括一种原型链的特性,许可对象继承到另一个对象的属性。正确地运用它能削减对象初始化时的斲丧的时候和内存。
检索
.,[]两种检索体式格局,引荐点.示意法。
尝试重undefined的成员属性中取值将会致使TypeError非常,这时候能够经由历程&&来防止毛病。
更新
假如属性名已存在对象里。那末属性的值会被替换。假如之前没有具有谁人属性名,那末该属性将被扩大到对象中。
援用
对象经由历程援用来通报。它们永久不会被复制。
原型
一切经由历程对象字面量建立的对象都链接到Object.prototype
建立新对象时,能够挑选某个对象作为它的原型。

if (typeof Object.create !== 'function') {
  Object.create = function(o) {
    var F = function () {};
    F.prototype = o;
    return new F();
  };
}

原型衔接只要在检索值的时刻才被用到。假如尝试去猎取对象的某个属性值,但对象没有此属性名,那末JavaScript会试着从原型对象中猎取属性值。假如谁人原型对象也没有该属性,那末再从它的原型中寻觅,依此类推,直到该历程末了抵达尽头Object.prototype。假如想要的属性完整不存在原型链中,那末效果就是 undefined值。这个历程称为托付
原型关联是一种动态的关联。
反射
原型链上的一切属性都邑发作值。有两种计划能够处置惩罚掉对象上不需要的属性。
①递次搜检时抛弃值为函数的属性。但有能够有些值确切是函数,所以该要领不可靠。
②运用hasOwnProperty要领,假如是对象具有独占的属性,则返回true。该要领不会搜检原型链。
罗列
for in能够遍历一个对象中一切的属性名。但包括函数和一些不关心的原型中属性。而且递次不确定,能够用 hasOwnProperty要领和typeof消除函数。
for 轮回不会涌现for in那些情况。
删除
delete运算符能够用来删除对象的属性。
削减全局变量的污染
能够把全局性的资本归入一个称号空间之下。如许做能削减争执。

第4章 函数

函数用于①代码复用②信息隐蔽③组合挪用。平常来讲,所谓编程,就是将一组需求分节成一组函数与数据构造的妙技。
JavaScript的函数就是对象。
函数对象衔接到Function.prototype(该原型对象本身衔接到Object.prototype)。
每一个函数在建立时会附加两个隐蔽属性,函数的上下文和完成函数行动的代码。
每一个函数对象在建立时也随配有一个prototype属性。它的值是一个具有constructor属性且值为该函数的对象。
函数字面量
函数字面量包括4个部份。①保留字function②函数名,能够省略,③一组参数④一组语句。
函数字面量能够涌现在任何许可表达式涌现的处所。一个内部函数除了能够接见本身的参数和变量,同时也能够自在接见把它嵌套在个中的父函数的参数和变量。经由历程函数字面量建立的函数对象包括一个衔接到外部上下文的衔接。这被称为闭包
挪用
除了声明时定义的情势参数,每一个函数还吸收两个附加的参数:thisargument。在JavaScript中一共有四种挪用情势。①要领挪用情势,②函数挪用情势③组织器挪用情势④apply挪用情势。

this指向题目一向搅扰许多人。我平常是如许记的,谁挪用this就指向谁。)

要领挪用情势
对象的要领实行,this指向该对象。比方:

var myObj = {
  value: 0,
  showValue: function() {
    console.log('value:', this.value);
  }
}
myObj.showValue();  // value: 0

函数挪用情势

var add = function(a,b) {
    return a + b;
}
add(3,4);  //7
window.add(3,4);  //7
// 这类this被绑定到全局对象(window)。
// 能够明白是window.add(3,4);

有种简朴的方法就是var that = this;this存储下。
例:

var myObj = {
  value: 0,
  age: 20,
  showValue: function() {
    console.log('value:',this.value);
    var  that = this;
    var showAge = function() {
        // window上没有age,所所以undefined
        console.log('这里的this是window ---age:', this.age);  // undefined
        console.log('age:', that.age);  // 20
     }
     showAge();
  }
}
myObj.showValue();  // 0, undefined,

组织器挪用情势
JavaScript是一门基于原型继承的言语。
假如在一个函数前面带上new 来挪用。那末背地利将会建立一个衔接到该函数的prototype成员的新对象,同时this会被绑定到谁人新对象上。
new 前缀也会转变return 语句的行动。
例:

var Quo = function (string) {
  this.status = string;
}
Quo.prototype.get_status = function () {
  return this.status; 
}
var myQuo = new Quo('confused'); // 'confused'

一个函数,假如建立的目标就是愿望连系new 前缀来挪用。那末它就被称为组织器函数。根据商定,它们保存在以大写函数定名的变量里。假如挪用组织器函数时没有在前面加上new,能够会发作非常蹩脚的事变,既没有编译时的正告,也没有运转时广告,所以大写商定非常主要。
作者不引荐这类情势的组织器函数。有更好的替换体式格局。
Apply挪用情势
JavaScript是一门函数式的面向对象编程言语,所以对象能够具有要领。
apply要领让我们构建一个参数数组通报给挪用函数,它也许可我们挑选this的值。
参数
arguments,虽然具有length属性,但不是真正的数组。而是相似数组(array-like)的对象。
返回
return 可用来是函数提早返回。当return 被实行时,函数马上返回而不再实行余下的语句。
一个函数总会返回一个值,假如没指定,那就是返回undefined值。
假如函数挪用时在前面加上了new 前缀,且返回值不是一个对象,则返回this(该新对象)。
非常
JavaScript供应了一套非常处置惩罚机制。
throw语句和try catch,try catchfinally是可选的。
扩大范例的功用
JavaScript许可给言语的基础范例扩大功用。在第3章中我们已看到,能够经由历程Object.prototype增加要领,能够让该要领对一切对象都可用。如许的体式格局对函数、数组、字符串、数字、正则表达式和布尔值一样实用。

比方:

Function.prototype.method = function () {
  this.prototype[name]  = func;
  return this;
}

基础范例的原型是公用构造,所以在类库混用时务必警惕。一个保险的做法就是只在确认没有该要领时才增加它。

Function.prototype.methods = function(name, func) {
  if (!this.prototype[name]) {
      this.prototype[name] = func;
  }
  return this;
}

递归
递归函数就是会直接或间接地挪用本身的一种函数。递归是一种壮大的编程手艺,递归是用平常的体式格局去处理每一个子题目。书中举了一个汉诺塔的例子,是递次设想中典范递归题目。细致申明能够拜见 百度百科“汉诺塔”词条
一些言语供应了尾递归优化。尾递归是一种在函数的末了实行挪用语句的特别情势的递归。拜见Tail call。 ES6版本扩大了尾递归。拜见阮一峰先生的《ES6规范入门》中的尾挪用优化
作用域
在编程言语中,作用域掌握着变量与参数的可见性和声明周期。
书中指出当前JavaScript没有块级作用域。因为没有块级作用域,所以最好的做法是在函数体的顶部声明函数中能够用到的一切变量。不过ES6扩大了有块级作用域。
闭包
作用域的长处是内部函数能够接见定义它们的外部函数的参数和变量(除了thisarguments)。
例子:

<ul class="list">
    <li>0</li>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>
// 点击相应节点时,显现对应的序号。能够运用闭包来处理。
var add_the_handlers = function() {
    var helper = function(i) {
        return function(e) {
            alert(i);
        }
    }
    var i;
    for (i = 0; i < nodes.length; i += 1) {
        nodes[i].onclick = helper(i);
    }
}
// 扩大 别的能够用let i = 0,或许把nodes类数组转成数组等计划完成。
// 闭包特性:1、函数内再嵌套函数,2、内部函数能够挪用外层的参数和变量,3、参数和变量不会被渣滓接纳机制接纳。
// 闭包长处 天真和轻易,便于封装。瑕玷:空间糟蹋、内存泄漏、机能斲丧。

回调
提议异步要求,供应一个当服务器相应抵达时随即动身的回调函数。异步函数马上返回,如许客户端就不会被壅塞。
模块
我们能够运用函数和闭包来组织模块。模块是一个供应接口却隐蔽状况与完成的函数或对象。
举例:给String增加一个deentityify要领。它的使命是寻觅字符串中的HTML字符实体并把它们替换成对应的字符。

String.method('deentityify', function () {
    // 字符实体表。它映照字符实体的名字到对应的字符。
    var entity = {
        quot: '"',
        lt: '<',
        gt: '>'
    };
    // 返回 deentityify要领
    return function () {
        return this.replace(/&([^&;]+);)/g,
        function (a,b) {
            var r = entity[b];
            return typeof r === 'string'? r : a;
        }
    };
}());

模块情势运用了函数作用域和闭包来建立被绑定对象与私有成员的关联,在上面例子中,只要deentityify要领有权接见字符实体表这个数据对象。
模块情势的平常情势是:一个定义了私有变量和函数的函数;运用闭包建立能够接见私有变量和函数的特权函数;末了返回这个特权函数,或许把它们保存到一个能够接见的处所。
运用模块情势就能够摒弃全局变量的运用。它促进了信息隐蔽和其他优异的设想实践。关于运用递次的封装,或许组织其他单例对象,模块情势非常有效。

单例译注

模块情势一般连系单例情势运用。
JavaScript的单例就是用对象字面量示意法建立的对象,对象的属性值能够是数值或函数,而且属性值在该对象的生命周期中不会发作变化。更多内容拜见:
单例情势

级联
有一些要领没有返回值。假如我们让这些要领返回this而不是undefined,就能够启用级联。
在一个级联中,我们能够在零丁一条语句中顺次挪用同一个对象的许多要领。比方jQuery猎取元素、操纵款式、增加事宜、增加动画等。
柯里化
柯里化,是把多参数函数转换为一系列单参数函数并举行挪用的手艺。更多概况可拜见:柯里化
函数也是值。柯里化许可我们把函数与通报给它的参数相连系,发作一个新的函数。

var add1 = add.curry(1);
document.writeln(add1(6));

JavaScript并没有curry要领,但能够扩大该功用。
arguments不是真正的数组,所以运用了Array.prototype.slice要领。

Function.method('curry',function(){
    var slice = Array.prototype.slice,
    args = slice.apply(arguments),
    that = this;
    return function() {
        return that.apply(null, args.concat(slice.apply(arguments)));
    }
});

影象
函数能够将先前操纵的效果记录在某个对象里,从而防止无谓的重复运算。这类优化称作影象。
比方说,我们想要一个递归函数来盘算Fibonacci(斐波那契)数列,它的特点是,前面相邻两项之和即是后一项的值。更多参考:斐波那契。最前面两个数字是0和1。

var fibonacci = function() {
    return n < 2? n : fibonacci(n-1) + fibonacci(n-2);
}

如许虽然能完成事变,但它做了许多无谓的事变。
组织一个带有影象功用的函数:

var memoizer = function(mome, formula) {
    var recur = function(n) {
        var result = meno[n];
        if (typeof result !== 'number') {
            result = formula(recur, n);
            meno[n] = result;
        }
        return result;
    };
    return recur;
}

再用这个memoizer函数来定义fibonacci函数,供应其初始的memo数组和formula函数。

var fibonacci = memoizer([0,1],function(recur, n){
    return recur(n-1) + recur (n-2);
})

极大的削减了我们的事变量。比方要发作一个影象的阶乘函数,只需要供应基础的阶乘公式即可:

var factorial = meoizer([1,1], function(recur, n){
    return n * recur(n-1);
});

第5章 继承

伪类
JavaScript的原型存在诸多矛盾。它不直接让对象从其他对象继承,反而插入了一个过剩的间接层:经由历程组织器函数发作对象。
Function组织器发作的函数对象会运转相似如许的一些代码:

this.prototype =  {constructor:this}

新函数对象被给予一个prototype属性,这个prototype对象是寄存继承特性的处所。

当采纳组织器挪用情势,即用new前缀去挪用一个函数时,函数实行的体式格局会被修正。假如new 运算符是一个要领而不是一个运算符,它能够像如许实行:

Function.method('new',function(){
    // 建立一个新对象,它继承自组织器函数的原型对象。
    var that = Object.create(this.prototype);
    // 挪用组织器函数,绑定 -this- 到新对象上。
    var other = this.apply(that,arguments);
    // 假如它的返回值不是一个对象,就返回该新对象。
    return (typeof other === 'object' && other) || that;
});

一切组织器函数都商定定名成大写字母。一种更好的备选计划就是基础不运用new
对象申明符
就是指传多个参数时,能够直接通报一个对象。
原型
能够用Object.create要领组织出更多实例来。
函数化
迄今为止,我们所看到的继承情势的一个缺点就是没法庇护隐私。对象的一切属性都是可见的。我们没法取得私有变量和私有函数。
荣幸的是,我们有一个更好的挑选,那就是运用模块情势
我们从组织一个天生对象的函数最先。我们以小写字母开首来定名。
该函数包括以下四个步骤
1、建立一个新对象。
2、有挑选地私有实例变量和要领。
3、给这个新对象扩大要领。
4、返回谁人新对象。
以下是一个函数化组织器的伪代码模板

var constructor = function (spec, my) {
    var that, 其他的私有实例变量;
    my = my || {};
    把同享的变量和函数增加到my中
    that = 一个新对象
    增加给 that 的特权要领
    return that;
}

函数化情势有很大的天真性。它比拟伪类情势不仅带来的事变更少,还让我们更好的封装和信息隐蔽,以及接见父类要领的才能。
部件
我们能够从一套部件中把对象组装出来。

第6章 数组

数组是一段线性分派的内存,它经由历程整数盘算偏移并接见个中的元素。
数组是一种机能精彩的数据构造。不幸的是,JavaScript没有像此类数组一样的数据构造。
数组字面量
对象字面量
数组继承了Array.prototype大批有效的要领。而对象字面量是继承自Object.prototype
数组有length属性,而对象没有。
长度
每一个数组都有一个length属性。
能够直接设置length的值。设置更大的length不会给数组分派更多的空间,而设小致使一切下标大于即是新length的属性被删除。

var arr = [1,2,3];
arr.length = 1;
console.log(arr) // [1]

也能够经由历程length来经由历程增加值

var arr = [1,2,3];
arr[arr.length] = 4;
console.log(arr) // [1,2,3,4]

偶然用push要领更轻易。
删除
因为JavaScript的数组也是对象,所以delete运算符能够用来从数组中移出元素。移除后,长度稳定,原位置上变成了undefined
能够运用Array.prototype.splice要领删除数组。
罗列
JS数组就是对象,所以for in语句能够用来遍历数据的一切属性。
不过for in没法保证属性递次。而且能够从原型链中取得不测的属性。
for轮回能够防止以上题目。
轻易殽杂的处所

typeof [] === "object"; // true
typeof {} === "object"; // true

辨认是不是是数组。

// 要领一、
var is_array = function (value) {
  return value && typeof value === 'object' && value.constructor === Array;
};

但它在辨认从差别窗口(window)或帧(frame)里的组织的数组时会失利。
有一个更好的体式格局:

// 要领二、
var is_array = function (value) {
  return Object.prototype.toString.apply(value) === '[object Array]';
}

扩大
ES5 供应了Array.isArray()的要领。不过兼容性是IE9+。
要做到兼容,能够用以下要领。MDN上供应的。MDN Array.isArray

// 要领三、
if (!Array.isArray){
  Array.isArray = function(arg){
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}
var arr = [];
// 要领四
arr instanceof Array;
// 要领五
Array.prototype.isPrototypeOf(arr);
// 要领六
Object.getPrototypeOf(arr) === Array.prototype;

要领四、instanceof 运算符用来测试一个对象在其原型链中是不是存在一个组织函数的 prototype 属性。
要领五、isPrototypeOf() 要领用于测试一个对象是不是存在于另一个对象的原型链上。
要领六、[Object.getPrototypeOf() 要领返回指定对象的原型(即, 内部[[Prototype]]属性的值)。](https://developer.mozilla.org…
小结:除了要领二、三外,面临庞杂的环境,其他的都不能正确的推断是不是是数组。
要领
JavaScript供应了一套数组可用的要领,这些要领是被存储在Array.prototype中的函数。
Object.prototype是能够扩大的。
Array.prototype也是能够扩大的。
ES5中供应的Object.create要领。这要领用在数组是没有意义的,因为它发作的是一个对象,而不是一个数组,发作的对象将继承这个数组的值和要领,但它没有length特别属性。
指定初始值
JavaScript的数组一般不会预设值。书中写了一个轮回来扩大,天生初始值。
扩大:ES6中供应了fill来添补。比方:

['a','b','c'].fill(0);   // [0,0,0]
new Array(3).fill(0);   // [0,0,0]

// fill要领还能够接收第二、第三个参数,用于指定添补的肇端位置和完毕位置(不包括)。
new Array(3).fill(0,1,2); // [ ,0, ,]  空位不是undefined。空位没有任何值。ES6则是明白将空位转为undefined。

第7章 正则表达式

正则表达式对字符串中的信息完成查找、替换和提取操纵。
可处置惩罚正则表达式的要领有regexp.execregexp.teststring.matchstring.searchstring.split。一般来讲,正则相较于等效的字符串处置惩罚有着明显的机能上风。

一个例子

// 正则表达式必需写在一行中
var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;
var url = "http://www.ora.com:80/goodparts?q#fragment";
var result = parse_url.exec(url);
// ……

顺次婚配到的是:

url: 'http://www.ora.com:80/goodparts?q#fragment',
scheme: 'http',
slash: '//'
host: 'www.ora.com'
port:'80'
path:'goodparts'
query: 'q'
hash: 'fragment'

个人扩大:这里引荐 在线测试正则表达式的网站regex101,默许是PHP言语,挑选JavaScript言语。
在线图形化RegExp东西
MDN RegExp.prototype.exec()
也许诠释下这个正则,
这里的^ 肇端位置,$完毕位置
() 分组捕捉 ?:不捕捉
.示意除换行之外的恣意单个字符,关于码点大于0xFFFFUnicode字符,点(.)不能辨认(ES6中加u修饰符才可辨认),+示意一个或多个,*示意零个或多个,?示意0个或一个。[]示意或许,内里相符一个即可。
\d示意数字0-9
不严谨的正则表达式是一个罕见的安全漏洞的发源地。在实行某些婚配时,嵌套的正则表达式也能致使极为卑劣的机能题目。因而简朴是最好的战略。

再看一个 婚配数字的例子。

var parse_number = /^-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?$/i;
parse_number.test('1'); // true
parse_number.test('number'); // false
parse_number.test('98.6'); // true
parse_number.test('132.21.86.100'); // false
parse_number.test('123.45E-67'); // true
parse_number.test('123.45D-67'); // false

构造
有两个要领来建立一个RegExp对象。优先斟酌的是正则表达式字面量,另有一种体式格局是new RegExp('','g')
正则表达式标识:g全局(婚配屡次,差别的要领对g标识的处置惩罚提防各不雷同),i疏忽大小写。m多行
元素
正则表达式分支
|示意或,也示意分支 比方:

'info'.match(/in|int/)  // 婚配胜利,["in", index: 0, input: "info"]

正则表达式序列
一个正则表达式序列饱和一个或多个正则表达式因子。每一个因子能挑选是不是追随一个量词,这个量词决议着这个因子被许可涌现的次数,若没指定,这个因子则只婚配一次。
正则表达式因子

\ / [ ] () { } ? + * | . ^ $

正则表达式转义
\ 表转义 \f 分页 \n 换行 \r回车 \t 制表
\u 许可制订一个 Unicode 字符来示意一个十六进制的常量。
\d 等同于[0-9] D 取反等同于 [^0-9]
\s Unicode 空缺符一个不完整子集。 S 与s相反
\w [0-9A-Z_a-z] W 与其相反 [^0-9A-Z_a-z]
\b 示意 字边境
\1 示意 分组1所捕捉的文本的一个援用,所以它能被再次婚配。
\2 示意 指向分组2的援用,\3 是示意分组3的援用,以此类推。
正则表达式分组
捕捉型 ()
非捕捉型?:
向前正向婚配?=
有一个(?=前缀。它相似于非捕捉范例分组,但在这个组婚配后,文本会倒回到它它最先的处所,实际上并不婚配任何东西。也能够明白为婚配位置。
向后负向婚配
有一个(?!前缀。它相似于向前正向婚配分组,但只要当它婚配失利时它才继承向前举行婚配。这不是一个好的特性。
正则表达式字符集
正则表达式字符集是一种指定一组字符的方便体式格局。比方,要婚配一个元音字母,(?:a|e|i|o|u),能够轻易的写成[aeiou]
类供应别的两个方便:①指定字符局限
所以,一组由32ASCII的特别组合,能够写成[!-\/:-@\[-{-~]`
②类的取反
取反

[^!-\/:-@\[-`{-~]

正则表达式字符转义
字符类内部的转义划定规矩和正则表达式因子的比拟稍有差别。下面是在字符类中需要被转义的特别字符。

- / [ \ ]

正则表达式量词
量词后缀决议正则表达式因子应当被婚配的次数。
{3}三次
{3,6} 3、4、5、6次
{3,}3次或更屡次
?等同于{0,1}*等同于{0,}+等同于{1,}

第8章 要领

Array

array.concat(item…)
concat 要领发作一个新数组,它包括一份array的浅复制并把一个或多个参数item附加在厥后。假如item是数组,那末每一个元素分别被增加。背面有和它功用相似的array.push(item...)要领。

var a = ['a','b','c'];
var b = ['x','y','z'];
var c = a.concat(b, true);
// c => ['a','b','c','x','y','z',true]

扩大: ES6 有更便利的扩大运算符...

var a = ['a','b','c'];
var b = ['x','y','z'];
var c = [...a,true,...b];   // ["a", "b", "c", true, "x", "y", "z"]

array.join(separator)
join要领把一个array组织成一个字符串。
separator 默许值就是逗号','
假如你想把大批的字符串片断组装成一个字符串,把这些片断放在一个数组中,并用join要领衔接起来一般比用+元素运算符衔接起来要快。

译注:关于
IE6/7,运用join衔接大批字符串效力确切优于加号运算符。但现在主流浏览器,包括
IE8今后的版本,都对
+元素运算符衔接字符串做了优化,机能已明显高于
Array.join()。所以现在大多数情况下,发起首选运用+ 衔接字符串。更多参看《高机能网站建立进阶指南》中字符串优化相干章节。

array.pop()
pop要领移除array中的末了一个元素,并返回这个元素。假如array为空,则返回undefined

var a = ['a','b','c'];
var c = a.pop(); // a 是 ['a','b']  c是 'c'
// pop 能够像如许完成。
// 这里的 Array.method()在第一章例子中已定义了,而且贯串全书。实在就是相当于Array.prototype
Array.method('pop', function () {
    return this.splice(this.length-1,1)[0];
});

array.push(item…)
concat差别的是,它会修正array,假如参数item是数组,它会把参数数组作为单个元素全部增加到数组中。并返回这个array的新长度值。

var a = [1,2,3];
var b = [4,5,6];
var c = a.push(b,true);
// a 是 [1,2,3,[4,5,6],true]
// c 是 5

push能够像如许完成:

Array.method('push', function () {
  this.splice.apply(
  this,
  [this.length,0].
  concat(Array.prototype.slice.apply(arguments)));
  return this.length;
});

array.reverse()
reverse反转array元素递次,并返回array本身。

var a = [1,2,3];
var b = a.reverse();
// a 和 b都是 [3,2,1]

array.shift()
shift移除array的第一个元素并返回这个元素。假如array为空,则返回undefinedshift一般比pop慢的多。

var a = [1,2,3];
var c = a.shift(); // a 是[2,3] , c 是1

shift能够如许完成:

Array.method('shift', function(){
    return this.splice(0,1)[0];
});

array.slice(start[, end])
slice是对array中的一段做浅复制。end是可选的。默许是array.length,假如两个参数任何一个是负数,array.length会和相加。假如start大于array.length,取得一个[],字符串也有Sting.slice这个同名要领。
array.sort
默许不能给一组数字排序。默许把要被排序的元素都视为字符串。
荣幸的是,能够运用本身的比较函数替换默许的比较函数。
比较函数应当接收两个参数,而且假如这两个参数相称则返回0,假如第1个参数应当分列在前面,则返回一个负数,假如第二个参数应当分列在前面,则返回一个正数。
sort要领是不稳定的。JavaScriptsort要领的稳定性依据差别浏览器的完成而不一致。
可拜见MDN sort
array.splice(start, deleteCount,item…)
splice要领从array中移除一个或多个元素,并用新的item替换它们。

// splice 能够像如许完成
Array.method('splice',function (start, deleteCount) {
    var max = Math.max,
        min = Math.min,
        delta,
        element,
        insertCount = max(arguments.length - 2, 0),
        k = 0,
        len = this.length,
        new_len,
        result = [],
        shift_count;
    start = start || 0;
    if (start < 0) {
        start += len;
    }
    start = max(min(start, len), 0);
    deleteCount = max(min(typeof deleteCount === 'number' ? deleteCount : len, len - start), 0);
    delta = insertCount - deleteCount;
    new_len = len + delta;
    while (k < deleteCount) {
        element = this[start + k];
        if (element !== undefined) {
            result[k] = element;
        }
        k += 1;
    }
    shift_count = len - start - deleteCount;
    if (delta < 0) {
        k = start + insertCount;
        while (shift_count) {
            this[k] = this[k - delta];
            k += 1;
            shift_count -= 1;
        }
        this.length = new_len;
    } else if (delta > 0) {
        k = 1;
        while (shift_count) {
            this[new_len - k] = this[len - k];
            k += 1;
            shift_count -= 1;
        }
        this.length = new_len;
    }
    for (k = 0; k < insertCount; k += 1) {
        this[start + k] = arguments[k + 2];
    }
    return result;
});

array.unshift(item…)
unshift 要领像push要领一样,不过是用于把元素增加到数组的最先部份,返回新arraylength

// unshift 能够像如许完成
Array.method('unshift', function(){
    this.splice.apply(this,
    [0,0].concat(Array.prototype.slice.apply(arguments)));
    return this.length;
});

Function

function.apply(thisArg,argArray)
apply要领挪用function,通报一个会被绑定到this上的对象和一个可选的数组作为参数。

Number

number.toExponential(fractionDigits)
toExponential要领 把这个number转换成一个指数情势的字符串。可选参数掌握其小数点后的数字位数。它的值必需在0~20

number.toFixed(fractionDigits)
toFixed要领把这个number转换成一个十进制数情势的字符串。可选参数掌握其小数点后的数字位数。它的值必需在0~20。

number.toPrecision(precision)
toPrecision要领把这个number转换成一个十进制数情势的字符串。可选参数掌握数字的精度。它的值必需在0~21

number.toString(radix)
number转换成字符串。可选参数掌握基数。它的值必需是2~36。默许的radix是以10为基数的。radix参数最经常使用的是整数,然则它能够用恣意的数字。

Object

object.hasOwnProperty(name)
假如这个object包括名为name的属性,那末返回true。原型链中的同名要领不会被检测。这个要领对name就是“hasOwnProperty”时不起作用。

RegExp

regexp.exec(string)
exec是正则中最壮大(和最慢)的要领。
假如胜利婚配,它会返回一个数组。下标为0 的元素包括正则婚配的子字符串。下标为1的则是分组1捕捉的文本。下标为2的则是分组2捕捉的文本。以此类推。假如婚配失利则返回null
regexp.test(string)
test是最简朴(和最快)的要领。婚配胜利,返回true,不然返回false。不要对这个要领运用g标识。
比方:

var reg = /\w+/g;
reg.test('ab'); // true
// 再实行一遍就是false了。
reg.test('ab'); // false
// 再实行一遍就是true了。
reg.test('ab'); // true
// 再实行一遍又是false了,云云重复,所以用g标识后,看起来很诡异。因为每次婚配最先位置变了。
reg.test('ab'); // false

test能够像如许完成:

RegExp.method('test', function(string){
    return this.exec(string) !== null;
});

String

string.charAt(pos)
返回在string中的pos位置处的字符。

string.charCodeAt(pos)
charAt一样,不过返回整数情势示意字符码位。

string.concat(string)
很罕用,用+号运算符更轻易。

string.indexOf(searchString,position)
string中查找第一个参数,假如被找到返回该字符的位置,不然返回-1position可设置指定位置最先查找。

string.lastIndexOf(searchString,position)
lastIndexOf 要领和indexOf要领相似,不过它是从末端最先查找,不是从头最先。

string.localeCompare(that)
比较两个字符串。相似于array.sort

string.match(regexp)
假如没有g标识,那末挪用string.match(regexp)和挪用regexp.exec(string)效果雷同。假如带有g标识,那末它天生一个包括一切婚配(除捕捉分组之外)的数组。

string.replace(searchValue,replaceValue)
string举行查找和替换操纵,并返回一个新的字符串。参数searchvalue能够是一个字符串也能够是一个正则表达式对象。参数replaceValue能够是一个字符串或一个函数。

string.search(regexp)
indexOf相似,不过它吸收正则为参数。

string.slice(start, end)
slice要领复制string的一部份来组织一个新的字符串。假如start参数是负数,它将与string.length相加。end参数是可选的。

string.split(separator,limit)
string支解成片断来建立一个字符串数组。可选参数limit能够限定支解的片断数目。separator参数能够是字符串或许正则。
string.substring(start,end)
slice要领一样,不过它不能处置惩罚负数参数。
string.toLocaleLowerCase()
它运用本地化的划定规矩把这个string中的字母转换成小写花样。这个要领主要用在土耳其语上。
string.toLocaleUpperCase()
它运用本地化的划定规矩把这个string中的字母转换成大写花样。这个要领主要用在土耳其语上。
string.toLowerCase()
返回新字符串,一切字母转成小写花样。
string.toUpperCase()
返回新字符串,一切字母转成大写花样。
String.fromCharCode(char…)
依据一串数字编码返回一个字符串。

var a = String.fromCharCode(67,97,116) // a是'Cat'

第9章 代码作风

这一章中,简短的说了一些代码作风。事实证明代码作风在编程中是很主要的。

第10章 幽美的特性

精简的JavaScript里都是好东西。
包括:1、函数是顶级对象;2、基于原型继承的动态作用域;3、对象字面量和数组字面量。

到此,念书笔记已结束。文章有什么不妥的地方,迎接指出~

关于

作者:常以轩辕Rowboat若川为名混迹于江湖。前端路上 | PPT爱好者 | 所知甚少,唯善学。
个人博客
segmentfault前端视野专栏,开通了前端视野专栏,迎接关注
掘金专栏,迎接关注
知乎前端视野专栏,开通了前端视野专栏,迎接关注
github,迎接follow~

    原文作者:若川
    原文地址: https://segmentfault.com/a/1190000010313101
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞