跳到主要内容

JavaScirpt语言精粹

快速的总结一本经典的书

通常是我的一家之言

将我觉得重点的东西快速的抄写或者简写下来

1.精华​

优秀的想法​

函数、弱类型、动态对象和富有表现力的对象字面量表示法。

糟糕的想法​

全局变量的编程模型

强类型并不会让测试工作更轻松

实践中,在工作中类型检查找到的错误并不是让人头疼的地方。

所以我认为 typescript 的主要作用其实是在代码里写注释(提高可读性和可维护性),编译检查并不能算是优点

2.语法​

空白​

注释​

使用 // 代替 /* */,因为后者在正则中可能出现

标志符​

不允许在对象字面量中

数字​

避免了短整型的溢出

字符串​

语句​

typeof 产生的值有'number'、'string'、'boolean'、'undefined'、'function'和'object'

3.对象​

数据类型​

javascript 的简单数据类型包括 数字、字符串、布尔值、null和undefined,其他都是对象。对象是无类型的。他对新类型的属性没有限制

字面量​

检索​

可使用.或[],优先使用.,因为更紧凑且可读性更好。如果尝试检索一个不存在的值,将会返回undefined

更新​

引用​

原型​

每个对象都连接到一个原型对象。并且可以从中继承属性。原型无法被更新,但可以被检索出来。

给object增加一个create方法,这个方法创建一个使用原对象作为其原型的新对象。

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

原型连接只有在检索的时候才可以被用到。如果我们尝试获取对象的某个值,但对象没有该属性名,那么 javaScript 会从原型对象中获取属性值。如果这个原型对象中也没有,那么他会从原型对象的原型对象中获取。以此类推,最终会返回到Object.prototype。如果该属性完全不存在在原型链中,那么结果就是 undefined。这个过程被称作委托。

原型关系是动态的,在链中添加一个属性,那么立刻在所有基于该原型创建的对象均可见

反射​

使用typeof 检查该属性是否为函数;使用hasOwnPrototype()检查,该函数不会返回原型链

枚举​

for in 会包含不需要的原型链。

删除​

全局变量​

只创建一个对象,所有的变量都在该对象下

4.函数​

在 javaScript 中,函数就是对象,函数对象连接到Function.prototype。该原型对象本身连接到Object.prototype。函数的与众不同就在于他可以被调用。

函数字面量​

函数字面量可以出现在任何表达式出现的地方。函数也可被定义到其他函数中。一个函数除了可以访问自己的参数和变量,也可以自由访问把他嵌套在其中的副函数的变量和参数。通过函数字面量创建的对象包含一个连到外部上下文的连接。这被称为闭包(closure)。它是 javascript 强大表现力的来源。

调用​

调用一个函数会暂停当前函数的执行,传递控制权和参数给新函数。除了声明时定义的形式参数,每个函数额外接收两个参数:this和arguments。参数this在面向对象编程中十分重要。它的值取决于调用的模式。javaScript 中一共有4种调用模式:方法调用模式、函数调用模式、构造器调用模式和apply调用模式。如果函数穿参的参数过少,则其与形式参数为undefined。过多的传参会被忽略。

方法调用模式​

当一个函数被保存为对象的一个属性时,我们称他为一个方法。当一个方法被调用时,this被绑定到该对象。

var myObject = {
value: 0,
increament: function (inc) {
this.value += typeof inc === 'number' ? inc : 1
}
}

函数调用模式​

当一个函数并非一个对象的属性时,那么他就是被当作一个函数来调用的。

var sum = add(3, 4)

此模式调用函数时,this被绑定到全局对象,不能利用内部函数来帮助他工作。不过有一个很容易的解决方案

myObject.double = function () {
var that = this // 解决方案
var helper = function () {
that.value = add(that.value, that.value)
}
helper()
}

构造器调用模式​

如果在一个函数前面带上new来调用,那么背地里将会创建一个连接到该函数的 prototyp 成员的新对象,同时this会被绑定到那个新对象上。

// 创建一个名为 Quo 的构造器函数,它构造一个带有 status 属性的对象
var Quo = function (string) {
this.suatus = string;
}
// 给 Quo的所有实例提供一个名为get_status 的公共方法
Quo.prototype.get_status = function () {
return this.status
}

// 构造一个Quo实例
var myQuo = new Quo("confused")
document.writeln(myQuo.get_status()) // 打印显示”confused”

apply调用模式​

因为 javaScript 是一门函数式的面向对象编程语言,所有函数可以拥有方法。

apply方法让我们构建一个参数数组传递给调用函数。它也允许我们选择this的值。

// 构建一个包含两个数字的数组,并将它们相加。
var arrray = [3, 4]
var sum = add.apply(null, array) // sum值为 7

// 构造一个包含status 成员的对象
var statusObject = {
status: 'A-OK'
}

// statusObject 并没有继承自Quo.prototype,但我们可以在statusObject 上
// 调用get_status 方法,尽管statusObject 并没有一个名为get_status的方法
var status = Quo.prototype.get_status.apply(statusObject)
// status 值为 'A-Ok'

参数​

返回​

如果函数调用时,且返回值不是一个对象,则返回 this

异常​

扩充类型的功能​

递归​

javascript 没有提供尾递归的优化

作用域​

尽管 javscript 貌似支持块级作用域,但是实际上并不支持

不过 javascript 拥有函数作用域。

::: note 目前javascript 在 es 标准的推动下已经支持,let 和 const 都是受限于块级作用域的 :::

闭包​

通过调用一个方法的形式去初始化myObject

var myObject = (function () {
var value = 0

return {
increament: function (inc) {
value += typeof inc === 'number' ? inc : 1
}
getValue: function () {
return value
}
}
}())

可以通过这种形式设计一个私有变量

// 创建一个名为quo的构造函数
// 它构造出带有 get_status 方法和 status 私有属性的一个变量
var quo = function (status) {
return {
get_status: function () {
return status
}
}
}

var myQuo = quo("amazed")

因为 get_status 方法并不是访问该参数的一个副本,它访问的是该参数本身。因为该函数可以访问它被创建时的上下文环境,这被称为是闭包

有个更有用的例子:

// 定义一个函数,它设置一个DOM节点为黄色,然后把它渐变为白色
var fade = function (node) {
var level = 1
var step = function () {
var hex = level.toString(16)
node.style.backgroundColor = '#FFFF' + hex + hex
if (level < 15) {
level += 1
setTimeout(step, 100)
}
}
setTimeout(step, 100)
}
fade(document.body)

回调​

需要响应的函数

模块​

级联​

返回this,可以使用下面的代码

getElement('myDiv')
.move(350, 150)

柯里化​

记忆​

5.继承​

在基于类的语言中,对象是类的实例,并且类可以从另一个类中继承。javaScript 是一门基于原型的语言,这也意味着对象可以其他对象继承

伪类​

对象说明符​

原型​

摒弃类,专注于对象

// 我们先用字面量构建一个有用的对象
var myMammal = {
name: 'Herb the Mammal',
get_name: function () {
return this.name
}
says: function () {
return this.saying || ''
}
}
// 可以通过之前的 Object.create() 快速构造出更多实例
var myCat = Object.create(myMammal)
myCat.name = 'Henrietta'
myCat.saying = 'meow'
myCat.purr = function (n) {
var i, s = ''
for (i = 0; i < n; i += 1) {
if (s) {
s += '-'
}
s += 'r'
}
return s
}

这是一种差异化继承

函数化​

部件​

6.数组​

数组字面量​

var numbers = ['zero', 'one', 'two', 'three', 'four']
var numbers_object = { 0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'}

长度​

删除​

枚举​

方法​

指定初始值​

7.正则表达式​

javascript 的正则表达式特性借鉴自 perl

例子​

结构​

元素​

正则表达式序列​

正则表达式因子​

正则表达式转义​

正则表达式分组​

正则表达式字符集​

正则表达式量词​

8.方法​

Array​

Array.concat(...item)​

Array.join(separator)​

Array.pop()​

Array.push(...item)​

Array.reverse()​

Array.shift()​

移除数组中的的一个元素

Array.slice(start, end)​

Array.soft()​

Array.splice()​

Array.unshift(item)​

Function​

Function.apply(thisArg. ArgArray)​

Number​

number.toExponential(fractionDigits)​

number.toFixed(fractionDigits)​

number.toPrecision(fractionDigits)​

控制数字精度

number.toString(radix)​

radix 位数

Object​

object.hasOwnProperty(name)​

Regexp​

regexp.exec(string)​

regexp.test(string)​

String​

string.charAt(pos)​

string.charCodeAt(pos)​

string.concat(string...)​

string.indexOf(searchString, positoin)​

string.lastIndexOf(searchString, positoin)​

string.localeCompare(that)​

string.match(regexp)​

string.replace(searchValue, replaceValue)​

string.search(regexp)​

string.slice(start, end)​

string.split(separator, limit)​

string.subString(start, end)​

string.tolocaleLowerCase()​

string.tolocaleUpperCase()​

string.toLowerCase()​

string.toUpperCase()​

string.fromCharCode()​

9.代码风格​

10.优美的特性​

附1:毒瘤​

浮点数​

二进制的浮点数不能正确地处理十进制的小数,因此0.1 + 0.2 不等于 0.3。可以通过指定精度来避免

NaN​

(完)