JavaScript语言精粹 笔记 (Javascript: The Good Parts)

一、简单数据类型

一共5个:Number、String、Boolean、null 和 undefind
Number、String、Boolean 拥有方法
简单/基本数据类型 均为 不可变类型(immutable)

不可修改 指 其内存中的值是不可变的,对这个变量重新赋值实际上是在内存中新建了一个值,将这个变量名指向了新建的值的地址

比如:

var s = "abcdefg";
var s2 = s;
s = "hijklmn";
console.log(s2);  
//此时s2仍为 "abcdefg"`

二、对象

除去简单数据类型,其他数据类型均为对象。对象均为可修改类型,在原地址上进行修改。
比如:

var arr = [1, 2, 3, s];
var arr2 = arr;
arr[0] = 5;
console.log(arr2);
//arr2为[5, 2, 3, "abcdefg"]

所以,对象是通过引用来传递的,不会被复制,若a=b=c={} 这样为引用同一个,若改变则三个一起变。

对象可以看作是可变的键值对、字典。
数组、函数、正则表达式 都是对象。对象是无类型的 class-free
key值带连接符“ - ”是不合法的,需要用双引号括起来,(一般的key值不用引号),而下划线“ _ ”是合法的。

三、原型 prototype

原型链只有在获取某属性值时才会用到。
一直往上追溯,直到终点Object.prototype的过程,叫委托
原型关系是动态关系:添加一个属性到原型中,会立即对所有基于该原型创建的对象生效。
person1.proto = Person.prototype
proto_是访问器,相当于索引,去找构造函数里的prototype
prototype是构造器,包含了构造函数里的各种方法。
所以,实例中是没有prototype属性的。
person2.constructor = Person
Person.prototype.constructor = Person
任意一个函数对象的_proto
是 f( ) {[ native code ]}

四、函数 Function

动态函数需要new一个实例,而静态函数可以直接调用。这里跟类class的逻辑类似。
比如:

function fnxx(){
	this.xx = function(){} //这个是动态方法
}
fnxx.abc = function(){} //这个是静态方法
调用:
fnxx.abc()
var _f = new fnxx();
_f.xx();

另:构造函数 如没有返回值的,会返回this。有return值时,仅返回return的内容。所以构造函数尽量不写return。

五、调用

javascript一共有四种调用模式:方法调用模式、函数调用模式、构造器调用模式和apply调用模式
调用运算符是跟在任何表达式后面的()

apply调用模式可以允许我们选择this值,第一个参数为新传入的obj,第二个参数为传递的参数数组。apply会把参数list自动打开,变成多个参数。注:传入和接收是不同的。
例子:

var arr = [3,4];
function add(...arr){  //这里用(a,b) 两个参数也可以
	return arr[0]+arr[1];
}
var sum = add.apply(null,arr);

调用 默认传参 arguments伪数组

六、异常 Exceptions

throw {name:" ", message:" "} throw中自定义参数,可以加别的属性,所有属性都会传递到catch中。
throw会中断函数执行,并抛出exception对象,进入catch(e){ e.name e.message} ,e就为throw中写的参数。

七、扩充类型方法 Augmenting Types

自定义新方法,扩充原型中的方法,方便调用。

//具体实现,给Function.prototype扩充
Function.prototype.method = function(name,func){
	this.prototype[name] = func;
	return this;
}
//定义
Number.method('integer',function(){
	return Math[ this<0 ? 'ceil' : 'floor'](this);
})
//使用
(-10/3).integer();

此处增加一个解释项: Fuction中为何包含Number

Number 是一个构造函数,因此它被链接到Function.prototype
原文:https://www.coder.work/article/1057512

此外,还可以直接进行定义,比较易读。

Number.prototype.integer = function(){
	return Math[ this<0 ? 'ceil' : 'floor'](this);
}

小tips:
console.dir()显示该对象所有的属性和方法

八、递归 Recursion

先举一个简单例子:

function fn(n){
	if(n>0){
		console.log(n); //3,2,1
		fn(n-1);
		console.log(n); //1,2,3
	}
}
调用 fn(3) 

解释:js是单线程,进入fn会打断现有执行,进入新线程,fn完成后,会回到这个线程执行下一行输出,所以是从最里层开始输出。

递归跟for循环最大的区别是:递归是先递到底,在归回来的时候,一块返回结果。

尾递归:函数最后return自身,运行时逻辑与‘循环’一致。按原理来说可以提升递归运行效率,因为不会在调用域里 创建新的作用域,从始至终只有一个作用域。但javascript并没有做尾递归优化,所以还是会与普通递归一致。此外,因为退出条件设置不当,很可能会变成深度递归,因堆栈溢出而运行失败。

九、自启动函数

正常函数会在定义之后 调用的时候运行,但也有些函数,需要在页面初始化的时候自动运行,也就是这里说到的 『.自启动函数』。
在讨论自启动函数之前,先来看一下两种函数定义方式。

  • 第一种,关键字+函数名,这种可以变量提升,即在定义之前,就可以调用。
fnName();
function fnName(){
    ...
}
  • 第二种,变量赋值,这种不能在定义之前使用,因为还未赋值,会报错。
fnName();
var fnName=function(){
    ...
}

这种定义方式,可以直接在后面接()调用,实现自启动。

var fnName=function(){
    ...
}();

待填坑:
汉诺塔

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值