Hackerrank网站上有一个10天的js教程,作为一个写js的半吊子正好可以过一遍来巩固下自己的js技能。
Table of Contents
Day 0: Hello World
- JavaScript程序是使用Unicode字符集编写的
- JavaScript对大小写敏感
- JavaScript忽略token之间的空白字符,包括换行
- 当两个语句在不同行上的时候,JavaScript语句末尾的分号是可以被省略的
- JavaScript中变量的命名规则与C语言类似,变量名由字母、数字、下划线或美元符号组成,且不能由数字开头
- JavaScript支持的注释方法和C++相同
Day 0: DataTypes
- JavaScript中的原始数据类型(primitive)共有六种:Number, String, Boolean, Symbol, Null, Undefined。他们不是对象而且没有成员方法。其他的数据类型都是Object
- Number
JavaScript中的数字类型只有双精度浮点数一种类型,没有整数相关的类型。一些特殊的值包括:Number.MAX_VALUE,Number.MIN_VALUE,Infinity,-Infinity,NaN,Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER。*Number.isSafeInteger()*方法可以用来判断一个Number是否是整数(并且该整数不能由其他整数转为双精度浮点数得到)。 - Symbol
Symbol可以用于作为Object属性的key。 - Null
null值表示一个空对象。 - Undefined
用于表示对象缺少某个属性或者一个变量只被声明没有被定义。
- Number
- JavaScript中的原始数据类型是immutable的,即他们的值不能被改变,只能声明新的变量来储存对原始数据类型变量值的操作结果
- 可以用typeof来判断变量类型
- 变量需要声明后才能使用或者在声明的时候就定义该变量,但是未初始化的变量其值为undefined
Day 1: Arithmetic Operators
- JavaScript支持**符号,表示幂运算
- JavaScript的switch语句可以是任意类型,不同于C语言
- JavaScript中的比较符号:
- ==
对于原始数据类型进行按值比较,对于对象数据类型则判断两个对象是否指向同一个对象 - !=
真值表与==相反 - ===
严格相等:- 操作数必须类型相同
- 操作数必须严格相等
- !==
非严格相等:真值表与严格相等相反
- ==
- 几个特殊的”假”值:
- false
- undefined
- null
- 0
- NaN
- “”
Day 1: Functions
- JavaScript通过function关键字,声明一个函数对象,函数默认返回undefined或者通过return语句返回其他值
- (Function Expression)函数表达式:在需要函数作为参数的地方,可以通过函数表达式直接定义一个匿名函数。函数表达式和函数的区别在于没有函数名。
Day 1: Let and Const
声明变量的三种方式:
- var
通过var声明的变量如果位于函数体内则其作用域为该函数,否则就是全局变量 - let
通过let声明的变量其作用域限于其位于的block - const
通过const声明的变量不能被赋予新值,并且声明的时候必须被初始化
Day 2: Loops
JavaScript支持的几种循环语句:
- for
- while
- do-while
- for-in
用于枚举Object的属性 - for-of
用于枚举Array,Map,Set,String,TypedArray,arguments等对象
Day 3: Arrays
- Array类的属性
Array.length - 成员函数
- Array.prototype.push
在末尾添加元素 - Array.prototype.forEach
遍历数组元素
- Array.prototype.push
fruits.forEach(function(item, index, array) {
console.log(item, index)
})
- Array.prototype.pop
移除最后一个元素 - Array.prototype.shift
移除第一个元素 - Array.prototype.unshift
在数组头部添加元素 - Array.prototype.indexOf
找到某个元素在数组中的索引 - Array.prototype.slice
数组浅拷贝 - Array.prototype.sort
数组排序,可以提供一个自定义的比较函数 - Array.prototype.splice
移除从某个索引开始的n个元素
let removedItem = fruits.splice(pos, 1)
Day 3: Try, Catch, and Finally
String Basics
string可以放在单引号或者双引号里面,双引号可以放在单引号里面来表示双引号字符,单引号可以放在双引号里面表示单引号字符
String的一些成员函数:
- String.charAt
- String.concat
- String.includes
- String.endsWith
- String.indexOf
- String.lastIndexOf
- String.match
在指定字符串中搜索正则表达式,返回一个Object,该Object具有三个属性:搜索的正则表达式,该正则表达式在该字符串匹配位置的索引,该字符串。 - String.search
同match,但是只返回匹配的索引。 - Strng.normalize
没看懂这个函数在干啥~ - String.repeat
- String.replace
- String.slice
与substring类似,但是可以接收负数(以字符串长度为模来进行运算)作为参数。 - String.split
- String.startsWith
- String.substr
substr([start[, length]])
- String.substring
substring([start[, end]])
substring方法会比较start和end大小,选择较小的为起点,较大的为终点(不含)。
- String.toLowerCase
- String.toUpperCase
- String.trim
- String.trimLeft
- String.trimRight
异常处理
异常处理的一般模式:
try {
} catch (e) {
} finally {
}
抛出异常的两种方式:
- 直接
throw vale
throw new Error(customError)
,这个customError
是一个字符串,通过catch捕获这个异常时,可以通过message属性访问这个字符串。
Day 4: Create a Rectangle Object
- JavaScript中的对象就是一堆属性的集合,属性的名字甚至可以是空字符串。
- 访问属性的方式有两种:
objectName.propertyName
objectName['propertyName']
- 构造对象的方式也有两种:
- 使用Object的初始构造函数
包括像map一样构造({property1:xxx,property2:xxx,property3:xxx}
)、使用new Object()
声明对象然后为属性赋值、使用Object.create
函数构造 - 使用自定义的构造函数配合new表达式
- 使用Object的初始构造函数
function Actor(firstName, lastName, Age) {
this.firstName = firstName;
this.lastName = lastName;
this.Age = Age;
}
Day 4: Classes
- Functional Classes
可以用函数来模拟类:
'use strict';
function Fruit (type) {
this.type = type;
this.color = 'unknown';
this.getInformation = getFruitInformation;
}
function getFruitInformation() {
return 'This ' + this.type + ' is ' + this.color + '.';
}
let lime = new Fruit('Mexican lime');
console.log(lime.getInformation());
lime.color = 'green';
console.log(lime.getInformation());
像上面代码中的getInformation函数也可以用匿名函数的方式直接定义在函数体内,但是这样会导致每定义一个Fruit对象时都会定义一个新的匿名函数。JavaScript中的每个函数都有一个Prototype属性,更好的做法是将getInfomation函数作为属性加入到Prototype属性中。
'use strict';
function Fruit (type) {
this.type = type;
this.color = 'unknown';
}
Fruit.prototype.getInformation = function() {
return 'This ' + this.type + ' is ' + this.color + '.';
}
let lime = new Fruit('Mexican lime');
console.log(lime.getInformation());
lime.color = 'green';
console.log(lime.getInformation());
- ClassesECMAScript6提供了类的语法糖,方便按照面向对象的方式编程。
- 构造函数constructor
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
let p = new Polygon(1, 2);
console.log('Polygon p:', p);
- Class Expressions
let Polygon = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
console.log('Polygon:', Polygon);
let p = new Polygon(1, 2);
console.log('p:', p);
let Polygon = class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
console.log('Polygon:', Polygon);
let p = new Polygon(1, 2);
console.log('p:', p);
- Prototype Methods在类的定义中直接实现的方法是Prototype Methods。
'use strict';
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
getArea() {
return this.height * this.width;
}
}
const square = new Polygon(10, 10);
console.log(square.getArea());
- Static Methods
如果函数声明时用了static关键字,那么只能通过类来调用该方法,不能通过该类的实例来调用该方法。 - 继承
通过extends关键字实现类的继承,子类通过super调用父类的构造函数和父类中定义的同名函数。
'use strict';
class Animal {
constructor(name) {
this.animalType = 'Animal'
this.name = name;
}
type() {
console.log(this.name, 'is type', this.animalType);
}
speak() {
console.log(this.name, 'speaks.');
}
}
class Dog extends Animal {
constructor(name, collarColor) {
super(name);
this.animalType = 'Dog';
this.collarColor = collarColor;
}
speak() {
console.log(this.name, 'barks.');
}
collar() {
console.log(this.name, 'has a', this.collarColor, 'collar.');
}
}
let spot = new Dog('Spot', 'red');
spot.type();
spot.speak();
spot.collar();
// Because the Animal constructor only expects one argument,
// only the first value passed to it is used
spot = new Animal('Spot', 'white');
spot.type();
spot.speak();
try {
spot.collar();
}
catch (exception) {
console.log(exception.name + ': ' + exception.message
+ ' (collar is a method of Dog, not Animal).');
}
Day 5: Template Literals
- 可以使用**`**来表示跨越多行的字符串。
- expression interpolation
可以用**${expression}**的方式在template literals中加入表达式或者直接使用字符串与表达式相加的方式。 - Tagged Template Literals
可以通过在每个**${expression}前面加一个名字的方式形成Tagged Template Literals**:
var a = 5;
var b = 10;
function foo(strings, ...values) {
console.log("." + strings[0] + ".");
console.log("." + strings[1] + ".");
console.log("." + strings[2] + ".");
console.log("." + strings[3] + ".");
console.log(values[0]);
console.log(values[1]);
console.log(values[2]);
}
foo`Sum ${a + b}
Product ${a * b}
Division ${b / a}`;
Day 5: Arrow Functions
这个教程里讲的Arrow Functions大概就是lambda表达式?
(parameter) => {statements}
parameter => {statements}
parameter => expression
parameter => {return expression}
(param1, param2, ..., paramN) => {statements}
(param1, param2, ..., paramN) => expression
(param1, param2, ..., paramN) => {return expression}
Day 7: Regular Expressions
- 创建Regular Expression Literal:
可以通过把正则表达式的pattern放在两个’/’中间的方式来创建正则表达式:
const re = /ab+c/;
或者直接声明一个正则表达式对象:
const re = new RegExp('ab+c');
- 正则表达式的flag参数:
/pattern/flags
和new RegExp(pattern[, flags])
两种方式都提供了一个可选的flags参数,flags可以是以下参数的组合: - g:全局搜索;
- i:忽略大小写;
- m:跨行搜索;
- u:Treat pattern as a sequence of unicode code points;
- y:sticky;
- 正则表达式中的回溯引用 问题:匹配同一个元音字母开头和结尾的字符串。需要使用回溯引用(backreference)来引用正则表达式前面部分匹配的结果(捕获组, capture groups)。
function regexVar() {
/*
* Declare a RegExp object variable named 're'
* It must match a string that starts and ends with the same vowel (i.e., {a, e, i, o, u})
*/
const re = /^([aeiou]).*\1$/;
/*
* Do not remove the return statement
*/
return re;
}
近期评论