基础语法
JS的基本类型
javascript的基本类型:undefined/null/boolean/number/string
确定一个变量是哪种基本类型用 typeof 操作符。
undefined与null
undefined表示某个变量不存在,或者没有为其分配值,而null则表示变量的值为空.
undefined和null的比较
- undefined==null => true
- undefined===null => false
boolean
boolean只有false和true两个值
除了以下值,其余都能转换成true
1.undefined
2.null
3.0和-0
4.NaN
5.空字符串
number
umber类型中包含整数型和浮点型
二进制表示:以零为开头,后面跟b或者B
八进制表示:以0开头,后面的数不能超过7
十六进制表示:0x或者0X开头
string
- 字符串类型的使用较多,更多用法见下引用类型中的String类
- 使用单引号’ '和双引号" "都可,不能中文标点“ ” 或’ ‘
- 比较两个字符串是否相等使用==
基本操作符
算术操作符
运算符 | 描述 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 求余 |
++ | 递加 |
– | 递减 |
赋值运算符
运算符 | 描述 |
---|---|
= | 赋值操作符 |
+= | 加法运算并赋值 |
-= | 减法运算并赋值 |
*= | 乘法运算并赋值 |
/= | 除法运算并赋值 |
%= | 取模运算并赋值 |
&= | 位与运算并赋值 |
^= | 位异或运算并赋值 |
l= | 位或运算并赋值 |
**= | ES7部分,表现不稳定 |
关系操作符
关系操作符有如下:
1.大于 >
2.小于 <
3.大于等于 >=
4.小于等于 <=
不同类型的比较情况
非数值与数值比较的时候,会先将非数值转换成数字,再进行比较
- 1>true => 1>1 => false
- 1>“0” => 1>0 => true
- 10>null => 10>0 => true (null转换成数字为0)
- 任何值和NaN作比较都是false
- 如果符号两侧都是纯字符串,依次比较ASCII值
- 汉字比较也是比较ASCII值
- 扩:如果两个操作数都是对象,则比较他们是否指向同一个对象
- 扩:如果一个操作数是对象,另外一个不是,则调用对象的ValuOf()方法,得到的结果按照前面的规则比较
布尔操作符
1.逻辑非 !
注意null、NaN、0、空字符串、undefined返回true
2.逻辑与 &&
逻辑与只有两者为true时才返回true,否则返回false
- 如果第一个操作数是对象,则返回第二个操作数。
- 如果第二个操作数是对象,则只有在第一个操作数的求值结果为true的情况下才会返回该对象。
- 如果两个操作数都是对象,则返回第二个操作数。
- 如果有一个操作数为null,则返回null。
- 如果有一个操作数是undefined,则返回undefined。
3.逻辑或 ||
逻辑或只有两者为false的时候才返回false,否则返回true
- 如果第一个操作数是对象,则返回第一个操作数。
- 如果第一个操作数的求值结果为false,则返回第二个操作数
- 如果两个操作数都是对象,则返回第一个操作数。
- 如果两个操作数都是null,则返回null。
- 如果两个操作数都是NaN,则返回NaN。
- 如果两个操作数都是undefined,则返回undefined。
控制语句
if语句
if (条件) {
如果条件为 true 时执行的代码
}
for语句
for (i = 0; i < 5; i++) {
text += "数字是 " + i + "<br>";
}
switch语句
switch(表达式) {
case n:
代码块
break;
case n:
代码块
break;
default:
默认代码块
}
while语句
只要指定的条件为 true,while 循环会一直循环代码块.
while (i < 10) {
text += "数字是 " + i;
i++;
}
do/While 循环
在检查条件是否为真之前,这种循环会执行一次代码块,然后只要条件为真就会重复循环
do {
要执行的代码块
}
while (条件)
while 循环会在指定条件为真时循环执行代码块。
while (条件)
{
需要执行的代码
}
for-in语句
var person = {fname:"Bill", lname:"Gates", age:62};
var text = "";
var x;
for (x in person) {
text += person[x];
}
console.log(text)
=> BillGates62
变量、作用域、内存
变量
- 在函数中使用var定义一个变量,那么这个变量在函数退出后就会被销毁
- 当省略var操作符的时候,会创建一个全局变量
- 对未初始化和未声明的变量执行typeof操作符都返回了undefined值
作用域与作用链
变量的作用域有两种:全部变量和局部变量
下文部分节选自:深入理解JavaScript中的作用域、作用域链和闭包
//这里在函数外部定义了scope,执行fn函数,打印变量输出为undefined(因为只要函数内定义了一个局部变量,函数在解析的时候都会将这个变量“提前声明)
<script>
var scope = "global";
function fn(){
console.log(scope);//result:undefined
var scope = "local";
console.log(scope);//result:local;
}
fn();
</script>
//相当于
<script>
var scope = "global";
function fn(){
var scope;//提前声明了局部变量
console.log(scope);//result:undefined
scope = "local";
console.log(scope);//result:local;
}
fn();
</script>
//不使用var关键字,会导致innerVar成为全局变量
<script>
function fn(){
innerVar = "inner";
}
fn();
console.log(innerVar);// result:inner
</script>
内存
Javascript具有自动垃圾收集机制:
- 最常用的垃圾收集方式是标记清除,“进入环境"和"离开环境”
- 不太常用的是引用计数,释放那些引用次数为零的值所占用的内存。
- 深入理解:JS进阶系列之内存空间
避免内存泄漏,可以释放该引用。
//但是如果一个值不再需要了,引用数却不为0,垃圾回收机制是无法释放这块内存,从而导致``内存泄漏```
例如:
const arr = [1,2,3,4,5];
console.log('hello world");
//arr的引用次数为1,尽管后面不再使用arr了,但是它还会持续占用内存,所以一般要这样处理
const arr = [1,2,3,4,5];
console.log('hello world");
arr = null;
引用类型
确定一个变量是哪种引用类型用instanceof操作符。
Array
array类型使用较多,以下是常用方法
- length() 数组长度
- pop() 删除最后一个元素
- push() 在末尾添加一个元素
- shift() 数组为空时不操作,返回undefined,否则删除并返回数组中第一个元素
- unshift() 向数组开头添加一个或者多个元素,并返回新的长度,改变原数组。
- join(separator) separator可选,默认为逗号分隔符,方法用于将数组中每一个元素放入一个字符串,不改变原数组。
//使用join()方法
var arr = new Array(3)
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"
//默认使用逗号作为分隔符
console.log(arr.join())
=> George,John,Thomas
var arr = new Array(3)
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"
//采用点号作为分隔符
console.log(arr.join("."))
=> George.John.Thomas
- split(separator,howmany) 把一个字符串分割成字符串数组 (可以使用正则表达式)
- separator 必须;howmany可选.该参数可指定返回的数组的最大长度
- splice(start,end) 方法可从已有的数组中返回选定的元素.返回截取的元素
- start 必须,规定从何处开始选取;
- 如果是负数,那么它规定从数组尾部开始算起的位置;
- end 可选,规定从何处结束选取(不包括end)
9.Array.isArray() 检测是否为数组
10.sort() 按照升序排列数组项 reverse() 反转数组的顺序
//compare的定义为
function compare(value1,value2)
{
if(value1 < value2)
{
return 1
}
else if(value1 > value2)
{
return -1
}
else
{
return 0
}
}
//通过传递compare函数到sort来进行比较
var values=[0,1,5,10,15]
values.sort(compare)
alert(values)
=> 0,1,5,10,15
11.toLocaleString()和toString() 返回由数组每个值的字符串形式拼接而成的一个以逗号分隔的字符串
12.valueof() 返回的是数组本身
13.indexOf()和lastIndexOf() 从数组的开头/末尾查找项
14.splice(index,howmany,item1,…,itemX) 数组删除、插入、替换函数
index 必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
howmany 必需。要删除的项目数量。如果设置为 0,则不会删除项目。
item1, …, itemX 可选。向数组添加的新项目。
//数组splice的应用(依次运行)
//声明数组
var colors=["red","green","blue"]
//删除
var removed=colors.splice(0,1)
colors=> green,blue
removed=>red
//插入
removed=colors.spliec(1,0,"yellow","orange")
colors=> green,yellow,orange,blue
removed=> 空数组
//替换
removed=colors.splice(1,1,"red","purple")
colors=>green,red,purple,orange,blue
removed=>yellow
15.迭代方法:对数组的每一项都运行给定的函数
- every()给定函数每一项都返回true,则返回true
- filter()返回true的项组成的数组
- forEach()没有返回值
- map()返回每次函数调用的结果组成的数组
- some()如果给定函数对存在一项返回true,则返回true
16.归并方法:
- reduce(callback(previousValue,currentValue,index,array),[initialValue])从数组的第一项开始,逐个遍历到最后
如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始。
//将二维数组转化为一维
let arr = [[0, 1], [2, 3], [4, 5]]
let newArr = arr.reduce((pre,cur)=>{
return pre.concat(cur)
},[])
console.log(newArr); // [0, 1, 2, 3, 4, 5
- reduceRight()从最后一项开始向前遍历到第一项
Object
对象定义,因为不具备传统的面向对象语言所支持的类和接口等基本机构
- 可用方括号访问对象类型,也可以用点表示法
var person={ "name":"Nicholas","age":29,5:true }
console.log(person["name"])
=> Nicholas
console.log(person.name)
=> Nicholas
Date
Date的初始化以及常用方法
1.初始化创建日期对象
- new Date()
- 构造函数的参数为日期的毫秒数,返回距离1970年1月1日经过该毫秒后对应的日期
var date=new Date(1222233);- var date1=new Date(‘2016-01-01’); //后台调用Date.parse()
- var date2=new Date(2016,4,5,17,55,55); //后台调用了Date.UTC()
2.Date.parse()接收一个日期字符串,返回该日期对应的毫秒数。
3.Date.UTC()
Date.UTC()的参数参数分别为年份,基于0的月份(0-11),月中的哪一天(1-31),小时数(0-23),分钟,秒以及毫秒。在这些参数中,只有前两个参数(年和月)是必需的。如果没有提供月中的天数,则假设天数为1,如果省略其他参数,则统统假设为0。返回该日期对应的毫秒数。
4.getTime() 获取对应的毫秒数
5.getFullYear() getMonth() getDate() getHours() getMinutes() getSeconds() getDay()分别获取年、月、日、小时、分钟、秒、星期几
6.setFullYear() setMonth() setDate() setHours() setMinutes() setSeconds() setDay()分别设置年、月、日、小时、分钟、秒、星期几
RepExp
//创建RepExp对象
new RegExp(pattern, attributes);
1.参数 pattern 是一个字符串,指定了正则表达式的模式或其他正则表达式
2.参数 attributes 是一个可选的字符串,包含"g"、"i"、"m"属性
属性 "g"、"i" 和 "m",分别用于指定全局匹配、区分大小写的匹配和多行匹配。
正则表达式语法总结见: JS正则表达式基本语法
RepExp的实例属性:
global:布尔值,表示是否设置了g标志
ignoreCase:布尔值,表示是否设置了i标志
lastIndex:整数,表示开始搜索下一个匹配项的字符串,从0算起
multiline:布尔值,表示是否设置了m标志
…
String
常用方法:
1.concat() 连接字符串。一般用于多个字符串连接,否则使用+即可
2.indexOf() 检索字符串是否存在另一字符串,不存在则返回 -1
3.lastIndexOf() 从后向前搜索
4.split() 分割字符串为字符串数组
5.toLocaleLowerCase() 或toLowerCase()转换成小写
6.toLocaleUpperCase() 或toUpperCase转换成大写
7.toString() 返回字符串
Function
定义函数可以使用Function构造函数。
Function构造函数可以接收多个参数,但是最后一个参数始终都被看成是函数体。
不推荐使用这种方法定义函数,因为这种语法会导致解析两次代码(第一次是解析常规ECMAScript代码,第二次是解析传入构造函数中的字符串,从而影响性能)。不过这种语法对于理解"函数是对象,韩函数名是指针"的概念倒是十分直观的。
类
类实际上是一个“特殊的函数”,类语法由两部分组成:类表达和类声明
类声明
//类的声明
class Rectangle{
constructor(height,width){
this.height=height;
this.width=width;
}
}
类表达式
一个类表达式是定义类的另一种方式,可以是具名的或匿名的。
//匿名类
let Rectangle=class {
constructor(height,width){
this.height=height
this.width=width
}
console.log(Rectangle.name)
//output:"Rectangle"
//具名类
let Rectangle=class Rectangle2{
constructor(height,width){
this.height=height;
this.width=width;
}
};
console.log(Rctangle.name)
//output:"Rectangle2"
一个类定义的例子
//原型方法
//静态方法:调用静态方法不需要实例化该类,但不能通过一个类实例调用静态方法。静态方法通常用于为一个应用程序创建工具函数。
class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
let obj = new Animal();
obj.speak(); // Animal {}
let speak = obj.speak;
speak(); // undefined
Animal.eat() // class Animal
let eat = Animal.eat;
eat(); // undefined
类的公有字段和私有字段声明
class Rectangle {
//公有字段
height = 0;
width;
//私有字段:从类外部引用私有字段是错误的,它们只能在类里面中读取或写入
#_height = 0;
#_width;
constructor(height, width) {
this.height = height;
this.width = width;
}
}
//使用extend创建子类:如果子类中定义了构造函数,那么它必须先调用 super() 才能使用 this
class Animal{
construtor(name){
this.name=name;
}
speak(){
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name) {
super(name); // 调用超类构造函数并传入name参数
}
speak() {
console.log(`${this.name} barks.`);
}
}
var d = new Dog('Mitzie');
d.speak();// 'Mitzie barks.'
待总结:
JS中定义类的方法
函数表达式
函数声明提升:在执行代码之前会先读取函数声明。
//函数表达式
function HelloWorld(){
console.log("Hello world")
}
//匿名函数
var helloworld=function(){
console.loe("Hello World")
}
递归函数:函数自身调用,直至满足条件退出。
//递归函数举例:
var count = function( f(n){
if (n<=0)
{
return 0
}
else if(n>0 && n<=2 )
{
return 1
}
else
return f(n-1)+f(n-1)
})
递归中可以使用callee,callee在函数内部使用,代表函数的引用。argument.callee(arg)
顺便提及以下callbe和apply,讲一下callbe和apply两种方法。
call和apply都是属于Function.prototype,两个函数的作用是一样的(改变某个函数运行时的上下文),只是使用的方式不同。
call(thisObj, arg1, arg2, arg3, arg4);
apply(thisObj, [args]);
//用法1 -> 改变this指向
var obj = {
name: 'linxin'
}
function func() {
console.log(this.name);
}
func.call(obj); // linxin
//用法2 -> 借用别的对象的方法
//Person1.call(this) 的作用就是使用 Person1 对象代替 this 对象,
//Person2有了Person1 中的所有属性和方法了,相当于Person2继承了Person1的属性和方法。
var Person1 = function () {
this.name = 'linxin';
}
var Person2 = function () {
this.getname = function () {
console.log(this.name);
}
Person1.call(this);
}
var person = new Person2();
person.getname(); // linxin
//用法3 -> 调用函数
//apply、call 方法都会使函数立即执行,因此它们也可以用来调用函数。
function func() {
console.log('linxin');
}
func.call(); // linxin
总结
本文总结了JavaScript的部分基础知识,其中部分内容借鉴了其它人的博客。本文若有写错的地方,欢迎大家指出。后面会继续深入Javascript的相关知识,并总结一些关于前端开发框架的知识,感兴趣的话大家可以关注一下。
部分内容引用来源: