JS学习笔记

本文主要为JS的学习笔记,基于MDN的文档,尤其是A_re-introduction_to_JavaScript

JS学习笔记

基础类型

JS包含以下类型:

  • Number
  • String
  • Boolean
  • Symbol(ES2015新增)
  • Object
    • Function
    • Array
    • Date
    • RegExp
  • null
  • undefined

数字

在JavaScript中,除了BigInt,不存在整数类型,都是IEEE754的double类型,都是浮点数。

存在NaN Not a Number,也存在Infinity和-Infinity两个特殊值,可以用isFinite来判断。

字符串

都是UTF-16的编码单元的序列,每一个编码单元由16位二进制数来表示,由一个或两个编码单元来表示一个字符。

可以用.length属性(而不是方法)来获取长度。

其他类型

null表示空值,undefined表示未定义未从初始化的值,未初始化的变量就是undefined类型。

JS存在布尔类型,false 0 空字符串“” NaN null undefined都会被转换为false。可以用Boolean显示转换,或在if中隐式转换。

变量

存在三种声明变量方法,let const var。

let

声明块级作用域的本地变量,可选地初始化值。

const

声明不可修改的常量,在定义域内可见。

var

使用var在声明的整个函数都是可见的,没有块作用域的限制。

运算符

使用==运算符能够自动类型转换,如果不需要则使用===运算符。类似的还有!=和!==运算符。

控制结构

if else,while do-while和c语言类似。

for循环可以和c语言类似,但也存在不同的两种循环:for-of和for-in循环。

1
2
3
4
for (let value of array){
//do sth with the value
//用于数组值
}
1
2
3
4
5
for (let property in object){
//do sth with the object property
//用于遍历对象
//遍历数组会遍历数组所有可枚举属性,如method和name,不要遍历数组
}

switch可以基于数字或者字符串,记得break。

对象

可以简单理解未“名称-值”对,类似字典。在js中,除了核心类型,core object,一切都是对象。名称部分是字符串,值可以是一切数据类型。

创建空对象方法,其中更推荐第二种,因为JSON格式:

1
2
var obj = new Object();
var obj = {};

创建对象实例如下:

1
2
3
4
5
6
7
8
9
var obj = {
name: "carrot",
_for: "MAX",
details:{
color:"orange",
size:12
}

}

访问方法支持如下:

1
2
obj.details.color
obj["details"]["size"]

第二种方法有点在于可以被看做字符串,但可能无法在后期被编译器优化。

创建对象可以用函数,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
function Person(name,age){
this.name = name;
this.age = age;
}

function makePerson(first, last) {
return {
first: first,
last: last
};
}

var you = new Person('you',25)

数组

数组是特殊的对象,以数字为类型名,只能用[ ]访问,包含特殊的属性:length,他比最大索引值大1。

创建数组传统方法如下:

1
2
3
4
5
6
var a = new Array();
a[0] = "dog";
//或者
var a = ["dog","cat"];
a[100] = "fox";
a.length;//101

注意第二种,length的值,他比最大索引值大1。访问不存在的数组索引,会得到undefined。

除了传统for,for-of,还可以用forEach方法.如下所示:

| 参数 | 描述 | | :———————————– | :———————————————————– | | function(currentValue, index, arr) | 必需。 数组中每个元素需要调用的函数。currentValue必需。当前元素index可选。当前元素的索引值。arr可选。当前元素所属的数组对象。 | | thisValue | 可选。传递给函数的值一般用 “this” 值。 如果这个参数为空, “undefined” 会传递给 “this” 值 |

调用如下:

1
2
3
4
5
6
7
8
var arr = [1, 2, 3, 4, 5];

arr.forEach(function (item) {
if (item === 3) {
return;
}
console.log(item);
});

增加元素用.push。还有些其他方法,查表就行。

函数

没有返回值的函数会返回undefined,调用函数没有提供足够参数会被undefined替代,传入过多参数会被忽略。

函数访问了函数体内为arguments的内部对象,包含所有参数。如下实现avg的方法:

1
2
3
4
5
6
7
8
9
function avg(){
var sum = 0;
for (var i = 0, j = arguments.length;i<j;i++){
sum+= arguments[i];
}
return sum/ arguments.length;
}

console.log(avg(1,2,3,4,5,6));//3.5

可以使用剩余参数操作符,来实现上述功能:

1
2
3
4
5
6
7
8
9
10
11
12
function avg(...args){
var sum = 0;
for (var value of args){
sum += value;
}
return sum/ arguments.length;
}

console.log(avg(1,2,3,4,5,6));
avg.apply(null, [2, 3, 4, 5]);//使用apply来将数组传为参数列表,第一个参数为被当作this看待的对象。
numbers = [2,3,4,5]
avg(...numbers)//展开语法

js也可以创建匿名函数。也可以给函数命名来递归调用。

注意this指针的问题,this的上下文可变, 如果在一个对象上使用点或者方括号来访问属性或方法,这个对象就成了 this

举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function makePerson(first, last) {
return {
first: first,
last: last,
fullName: function() {
return this.first + ' ' + this.last;
},
fullNameReversed: function() {
return this.last + ', ' + this.first;
}
}
}
s = makePerson("Simon", "Willison");
s.fullName(); // "Simon Willison"
s.fullNameReversed(); // Willison, Simon
var fullName = s.fullName;
fullName(); // undefined undefined

.prototype是可以被所有实例共享的对象,当访问某个实例没有定义的属性时候,会检查.prototype里面是否存在。使用如下:

1
2
3
4
5
6
7
8
9
10
function Person(first, last) {
this.first = first;
this.last = last;
}
Person.prototype.fullName = function() {
return this.first + ' ' + this.last;
}
Person.prototype.fullNameReversed = function() {
return this.last + ', ' + this.first;
}

对于new,可以有下面的类似实现,注意apply

1
2
3
4
5
6
7
function trivialNew(constructor, ...args) {
var o = {}; // 创建一个对象
constructor.apply(o, args);
return o;
}
var bill = trivialNew(Person, "William", "Orange");
var bill = new Person("William", "Orange");

call函数可以用来设置this,用例如下:

1
2
3
4
5
6
7
8
function lastNameCaps() {
return this.last.toUpperCase();
}
var s = new Person("Simon", "Willison");
lastNameCaps.call(s);
// 和以下方式等价
s.lastNameCaps = lastNameCaps;
s.lastNameCaps();

内部函数

函数内部可以定义函数,,而且可以访问父作用域的变量。如下所示:

1
2
3
4
5
6
7
8
9
function parentFunc() {
var a = 1;

function nestedFunc() {
var b = 4; // parentFunc 无法访问 b
return a + b;
}
return nestedFunc(); // 5
}

这种方法可以减少全局变量,避免污染命名空间。

闭包

闭包样例如下:

1
2
3
4
5
6
7
8
9
function makeAdder(a) {
return function(b) {
return a + b;
}
}
var add5 = makeAdder(5);
var add20 = makeAdder(20);
add5(6); // 5+6=11
add20(7); // 20+7=27

当调用makeAdder时创建了作用域对象,带有属性a,然后makeAdder创建一个函数并返回。闭包就是函数与其被创建时候带有的作用域对象的组合。

Author

王钦砚

Posted on

2021-01-23

Licensed under

CC BY-NC-SA 4.0

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×