JavaScript语言精粹-读书笔记(3)

第六章 数组

在JS中数组和对象实质都是对象,数组的属性是连续的整数。typeof(Array) = ‘object’

// 判断数组的方法
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]';
}

数组中的方法存放在 Array.prototype 中,对象 Object.prototype 可以被扩充,数组的原型方法也可以被扩充。

Array.method('reduce', fucntion(f, value){
  for (let i = 0; i < this.length; i ++){
    value = f(this[i], value);
  }
  return value;
});
// 给数组扩展方法:传入一个函数和初始值,对数组的每一项运行函数。下面是实际案例。
let data = [1, 2, 3, 4];
var add = function(a, b) {
  retunr a + b;
}
var mult = function(a, b) {
  retunr a * b;
}
var sum = data.reduce(add, 0);
// 将数组执行add方法,初始值是0
var prodect = data.reduce(mult, 1);
// 将数组执行mult方法,初始值是1

一个数组可以通过下标设置属性,同时可以直接使用点语法设置属性。可以说,array.length 就是类似的对象的点语法。

JS 数组没有多维数组,支持元素为数组的数组,这里我们构造一个矩阵。

Array.matrix = function(m, n, init) {
  var mat = [];
  for (var i = 0; i < m; i++) {
    a = [];
    for (var j = 0; j < n; j++) {
      a[j] = initial;
    }
    mat[i] = a;
  }
  return mat;
}

var myMatrix = Array.matrix(4, 4, 0);
document.writeLn(myMatrix);
// 生成一个0填充的 4*4 的矩阵。

// 单位矩阵
Array.identity = function(n) {
  let mat = Array.matrix(n, n, 0);
  for (let i = 0; i < n; i++) {
    mat[i][i] = 1;
  }
  return mat;
};
myMatrix = Array.identity(4);
document.writeln(myMatrix[3][3]);

第七章 正则表达式

正则表达式书写很复杂,后期维护相对复杂。写的时候最好是短小精悍。

var parse = /^(?:[A-Za-z]+)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;

// 划分网址

第九章 方法

Array

Array.concat 将多个数组,变量组合成一个新的数组。这个数组会浅复制一个数组,并将其他元素或者数组插入到新数组后面。

Array.join(seperator) 将数组的不同元素连接成字符串,原理是将每一项转化成一个字符串,将这些字符串连接。

Array.pop() 移出数组中的最后一个元素并返回(类似于堆栈stack),如果是空数组,那么返回undefined。

Array.push(item1, item2)在数组最后添加一个元素,原始数组改变,返回值是新数组的长度。

Array.reverse() 数组前后翻转,原始数组变成新数组,返回值就是新数组。

Array.shift() 移出数组的第一个元素(空数组返回undefined)shift 比 pop 速度慢很多。

array.unshift 在第一位增加元素,返回值是新数组的长度

array.slice(a, b) 浅复制数组的一部分,前面试闭区间后面是开区间;如果只有一个参数,表示从这个参数复制到数组的末尾。=>复制旧数组中的一部分

Array.sort() 字符串排序:可以给字符串进行排序,不能直接给数组排序(首先将数组转化成字符串,对字符串进行比较,通常会出错);当然,可以在此基础上,增加一个数组排序或者对象排序的方法。

Array.splice(a, b, c) 删除数组的一部分:将数组的a位置,删除b个元素,加入c元素。(c可选参数)

var a = [1, 2, 3];
var b = [4, 5, 6];
var c = a.concat(b, true);
a.push(6,7); // 这里改变数组a, 不会影响新的数组c。因为已经产生了新的数组c。
console.log(c);
// [1,2,3,4,5,6,true]

Function

// function.apply 传递一个绑定到 this 上的对象和一个可选的数组作为参数。
Function.method('bind', function(that) {
  // 返回一个函数。调用这个函数就是调用这个对象的一个方法
  var method = this;
  var slice = Array.prototype.slice;
  var args = slice.apply(arguments, [1]);
  return function() {
    return method.apply(that,
      args.concat(slice.apply(arguments, [0])));
  };
});

let x = function() {
  return this.value;
}.bind({ value: 666 });

alert(x());

数组的 call 和 apply :将一个对象的方法放在另一个对象上面,另一个对象可以使用这些方法。

Obj1.method1.call(Obj2, para1, para2); object 具有method1 方法,但是 object2 没有method1方法。所以这里Object2 借用object1 的method 方法,然后传入的参数是两个,进行继承。

Obj1.method2.apply(Obj2, [para1, para2]) apply 传入的参数是一个数组,其他的功能和效果类似。

详见 call.js 代码

Number

数值转化成不同字符串的几种方法

// toExponential() 转换成一个指数形式的字符串;
Math.PI.toExponential(2); // 3.14e+0

// toFixed 转化成一个十进制数的字符串,参数是小数点后的位数
Math.PI.toFixed(5); // 3.14159

// toPrecision 转化成一个十进制的字符串,参数是数字的精度
Math.PI.toPrecision(3); // 3.14

// toString(16) 转化成一个字符串,参数是转换的进制,默认是10
Math.PI.toSting();
Object

object.hasOwnProperty 这个方法可以监测对象的属性,但是原型链中的同名属性不会检查;

var a = {isLoading: true};
a.hasOwnProperty('isLoading') => true

var b = Object.create(a);
// 创建一个新对象b,其中的__proto__ 就是a, b对象可以访问a对象原型链上的方法和属性
b.hasOwnProperty('isLoading') => false
console.log(b.isLoading) => true
RegExp 正则表达式

exec

匹配字符串的最强大最慢的方法。如果匹配正则表达式,就返回一个数组,数组不同的项就是分组捕获的文本。如果匹配失败,就会返回 null。如果全局检索g,查找不会从这个字符串的开始位置,而是从regexp.lastIndex 开始。如果进行另一次查询,需要将 regexp.lastIndex 重置为0。

// 将HTML文本分解成标签和文本
var text = '<html><body bgcolor=linen><p>' + '</p></body></html>';
var tags = /[^<>]+|<(\/?)([A-Za-z]+)([^<>*])>/g;
var a, i ;

while ((a = tags.exec(text))) {
  for (i = 0; i < a.length; i++) {
    console.log((i + a[i]).entityify());
  }
}

test

匹配正则表达式最简答的方法,如果正则表达式匹配字符串,返回的是布尔值,不能使用全局的g标识。

var b = /&.+/.test('Tom &amp; beans');
RegExp.method('test', function(string) {
  return this.exec(string) !== null;
});
string

字符串的方法是最常用的方法

string.charAt(position); // 返回字符串中某个位置的字符,如果位置超过长度或者是负数,那么返回一个空字符串
string.charCodeAt(pos); // return 字符码位 if(pos > string.length) return NaN
string.concat('a', 'b'); //通常直接加号链接字符串即可
string.indexOf('test', 10); // 从位置10开始检错,查询test字符串,返回第一个匹配字符的位置,找不到返回-1
string.lastIndexOF('test', 3); // 从末尾开始查找
string.match(regexp) //让字符串和一个正则表达式进行匹配,依据g标识来决定怎样进行分配。如果没有g, string.match(regexp) 和 regexp.exec(string) 结果相同。如果regexp具有g标识,那么返回一个匹配的数组。
string.replace('search', 'replace'); // 如果标明g,就是替换第一个匹配的字符。
string.search(regexp); // 类似于indexOf 传入的参数是正则表达式,返回第一个匹配字符的首字符位置(没有position参数)
var text = 'hello world "anynone" tall';
var position = text.search(/["']/);

string.slice(start, end); // 复制string的一部分构造一个新的字符串。如果是负数,就从后面开始;默认end是string.length.
string.split(seperator, limit); // 将字符串按照分隔符分割成片段,并创建一个字符串数组。limit表示分割片段的数量。分隔符可以使字符串或者是正则表达式。如果分隔符是空字符,返回单字符的数组。

var ip = '192.168.0.1';
var b = ip.slice('.'); // ['192', '168', '0', '1']

string.toLowerCase();
string.toUpperCase();
string.fromCharCode(char...); //根据数字编码创建一个字符串 

截取一个字符串的方法:最好使用slice, 不要使用substring 因为后者无法使用负数;

第九章 代码风格

JS 对代码格式要求不要,容错性很高,这样可能造成bug。多写一个大括号可能避免if的作用范围。写合适的注释并及时更新注释(代码会更新,注释也需要更新)。详细的代码风格可以参考《代码整洁之道》这本书。

第十章 优美的特性

函数是顶级对象

函数具有词法作用域的闭包(lambda)

基于原型继承的动态对象

对象是无类别的。一个对象可以通过普通的赋值增加一个新成员属性;一个对象可以从另一个对象继承成员属性。

对象字面量和数组字面量

便捷的创建对象和数组(来源于JSON)

猜你喜欢

转载自blog.csdn.net/weixin_41697143/article/details/90706276