JavaScript学习笔记 - 基本概念

本文记录了我在学习前端上的笔记,方便之后的复习和巩固。javascript

3.1.4 严格模式

严格模式是JavaScript定义了一种不一样的解析和执行模型。在严格模式下ECMAScript3中的一些不肯定行为将获得处理,并且对某些不安全的操做也会抛出错误。要在整个脚本中启用严格模式,能够在顶部添加以下代码:前端

"use strict";

这段代码看起来像字符串,并且也没赋值给任务变量,但其实它是一个编译指示(pragma),用于告诉支持的JavaScript引擎切换到严格模式。这是为不破坏ECMAScript3而特地选定的语法。
在函数内部的上方包含这条编译提示,也能够指定函数在严格模式下执行:java

function doSomething() {
    "use strict";
    //函数体
}

3.2 关键字和保留字

ECMAScript5关键字:
break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with
ECMAScript5非严格模式保留字:
class、enum、extends、super、const、export、import
在严格模式下,第5版还对一下保留字施加了限制:
implements、package、public、interface、private、static、let、protected、yieldexpress

3.3 变量

局部变量被函数调用后,当前函数退出后就会被销毁,例如:数组

function test(){
    var message = "hi"; //局部变量
}
test();
alert(message); //错误

全局变量就不会:安全

function test(){
    message = "hi"; //全局变量
}
test();
alert(message); // "hi"

这样,只要调用过一次test()函数,这个变量就有了定义,就能够在函数外部任何地方被访问到。但全局变量的作法不推荐。由于在局部做用域中定义的全局变量很难维护。
严格模式下不能定义名为evalarguments的变量,不然会致使语法错误。函数

3.4 数据类型

ECMAScript中有五种简单数据类型:性能

  • Undefined学习

  • Null测试

  • Boolean

  • Number

  • String

还有一种复杂数据类型——Object

注意:ECMAScript6还新增了一种数据类型符号对象 - (Symbol) - 符号对象简介

3.4.1 typeof操做符

用于检测给定变量的数据类型——typeof就是负责提供这方面信息的操做符。对一个值使用typeof操做符可能返回下列某个字符串:

  • "undefind"——若是这个值未定义;

  • "boolean"——若是这个值是布尔值;

  • "string"——若是这个值是字符串;

  • "number”——若是这个值是数值;

  • "object" ——若是这个值是对象或null;

  • "function"——若是这个值是函数
    下面是几个使用typeof操做符的例子:

var message = "some string";
alert(typeof message); //"string"
alert(typeof (message)); //"string"
alert(typeof 95); //"number"

注意:调用typeof null 会返回 "object",由于特殊值null被认为是一个空的对象引用。

3.4.2 Undefind类型

Undefined类型只有一个值即undefind。在使用var声明变量后但未对其加以初始化时,这个变量的值就是undefined,例如:

var message;
alert(message == undefined); //true
var message1 == undefined
alert(message1 == undefined); //true

typeof操做符对未初始化和未声明的变量都返回undefined

3.4.3 Null类型

Null类型是第二个只有一个值的数据类型,这个特殊的值是null。从逻辑角度看,null值表示一个空对象指针,而这也正是使用typeof操做符检测null值会返回"object"的缘由

var car = null;
console.log(typeof car); //"object"

若是定义的变量是为了之后要保存对象,那么最好该变量初始化为null值。

if(car != null){
    //对car对象执行某些操做
}

undefined值是派生自null的值得因此:

console.log(null == undefined); //true

3.4.4 Boolean类型

该类型只有两个字面值: truefalse
虽然Boolean类型只有两个字面值,可是能够调用Boolean()函数把值转换为对应的Boolean值:

var message = "Hello World!";
var messageAsBoolean = Boolean(message);

转换规程:

数据类型 转换为true的值 转换为false的值
Boolean true false
String 任何非空字符串 ""(空字符串)
Number 任何非零数字值(包括无穷大) 0和NaN
Object 任何对象 null
Undefined n/a undefined

3.4.5 Number类型

//十进制
var intNum = 55; //整数
//八进制
var octalNum1 = 070;//八进制56
var octalNum1 = 079;//无效的八进制数值——解析为79
var octalNum1 = 08;//无效的八进制数组——解析为8
//十六进制
var hexNum1 = 0xA; //十六进制的10
var hexNum2 = 0x1f;    //十六进制的31

八进制:第一位必须是零(0),而后是八进制数字序列(0~7).若是字面值中的数值超出了范围,那么前导零将被忽略,后面的数值当成十进制解析。
十六进制:前两位必须是0x,后跟任何十六进制数字(0~9,A~F)。

注意:在算数计算时,全部的八进制和十六进制表示的数值最终都将被转换成十进制。

1.浮点数值

浮点数值中必须包含个小数点

var floatNum1 = 1.1;
var floatNum2 = 0.1;
var floatNum3 = .1    //有效但不推荐

因为保存浮点数值须要的空间是整数数值的两倍,所以ECMAScript会不失时机的将浮点数值转换成整数值。

var floatNum1 = 1.;  //小数点后面没有数字——解析为1
var floatNum2 = 10.0 //整数——解析为10

对于极大或极小的数值,能够用e表示法。

var floatNum  = 3.125e7; //31250000

浮点数值最高精度是17位小数,但在进行算数计算时它的精度远远不如整数。例如0.1加0.2不是0.3 ,而是0.30000000000000004。这个小小的舍入偏差会致使没法测试特定的浮点数值。例如:

if(a + b == 0.3){        //不要这样作测试
    alert("You got 0.3");
}

在这个例子中若是两个数是0.05和0.25或者是0.15和0.15都不会有问题。所以永远不要测试某个特定的浮点数值。

3.NaN

NaN,既非数值,是这个特殊的数值,这个数值用于表示一个原本要返回的数值的操做数未返回数值的状况(这样就不会抛出错误了)。
NaN自己有两个非同寻常的特色。首先,任何涉及NaN的操做(例如NaN/10)都会返回NaN。其次NaN与任何值都不想等,包括NaN自己。例如:

console.log(NaN == NaN); //false

针对NaN这两个特色,ECMAScript定义了isNaN()函数。这个函数接受一个参数,该参数能够是任何类型,2️⃣函数会帮咱们肯定这个参数是否"不是数值"。
isNaN()接受到第一值后,会尝试将这个值转换为数值。任何不能被转换的数值的值都会致使这个函数返回true。例如:

console.log(isNaN(NaN));  //true
console.log(isNaN(10));  //false(10是一个数值)
console.log(isNaN("10"));  //false(能够被转换成数值10)
console.log(isNaN("blue"));  //true(不能转换成数值)
console.log(isNaN(true));  //flase(能够被转换成数值1)

isNaN也适用于对象,在基于对象调用isNaN()函数时,会首先调用valueOf()方法,而后肯定该方法返回的值是否能够转换为数值。若是不能,则基于这个返回值再调用toString()方法,再测试返回值

4.数值转换

有3分函数能够把非数值转换为数值:

  • Number()——可用于任何数据类型

  • parseInt()——专门用于把字符串转换成整数数值

  • parseFloat()——专门用于把字符串转换成浮点数值

Number()函数的转换规则以下

  • 若是是Boolean值,truefalse将分别被转换为1和0.

  • 若是是数字值,只是简单的传入和返回

  • 若是是null值,返回0

  • 若是是undefined,返回NaN

var num1 = Number("Hello world!");  //NaN
var num2 = Number("");              //0
var num3 = Number("000011");        //11
var num4 = Number("true");          //1

parseInt()
因为Number()在转换字符串时比较复杂并且不够合理,所以在处理整数的时候更经常使用的事parseInt()函数。

var num1 = parseInt("1234bule"); //1234
    var num2 = parseInt("");         //NaN
    var num3 = parseInt("0xA");      //10(十六进制数)
    var num4 = parseInt("22.5");     //22
    var num5 = parseInt("070");      //56(八进制数)
    var num6 = parseInt("70");       //70(十进制数)
    var num7 = parseInt("0xf");      //15(十六进制数)
    
    //在ES3和ES5存在分歧。例如:
    var num = parseInt("070");       //ES3认为是56(八进制)  ES5认为是70(十进制)
    
    //parseInt()函数有第二个参数:转换时使用的基数(进制)
    var num = parseInt("0xAF", 16)   //175(按十六进制解析)
    //使用了16进制参数,字符串能够不带0x
    var num1 = parseInt("AF", 16)    //175
    var num1 = parseInt("AF")        //NaN

不知道基数意味着让parseInt()决定如何解析字符串,所以为了不错误的解析,建议不管在什么状况都明确指定基数。

parseFloat()

var num1 = parseFloat("123bule");      //1234(整数)
var num2 = parseFloat("0xA");          //0
var num3 = parseFloat("22.5");         //22.5
var num4 = parseFloat("22.34.5");      //22.34
var num5 = parseFloat("0908.5");       //908.5
var num6 = parseFloat("3.125e7");      //31250000

3.4.6 String类型

1.字符字面量

String数据类型包含一些特殊的字符字面量,也叫转义序列,用于表示非打印字符,或者具备其余用途的字符。

2.字符串的特色

ECMAScript中的字符串是不可变的,也就是说,字符串一旦建立,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,而后在用另外一个包含新值得字符串填充该变量例如:

var lang = "Java";
lang = lang + "Script"; //JavaScript

3.转换为字符串

toString()方法

var age = 11;
var ageAsString = age.toString; //字符串"11";
var found = true;
var foundAsString = found.toString; //字符串"true";

数值、布尔值、对象、字符串值都有toString()方法。但nullundefined值没有这个方法。
toString()方法也跟上面的parseInt()方法相似同样有一个参数:输出数值的基数;

var num = 10;
console.log(num.toString());    //"10"
console.log(num.toString(2));    //"1010"
console.log(num.toString(8));    //"12"
console.log(num.toString(10));  //"10"
console.log(num.toString(16));  //"a"

在不知道要转换的值是否是null或undefined的状况下,还可使用转型函数String(),这个函数可以将任何类型的值转换成字符串。String()函数遵循下列转换规则:

  • 若是值有toString()方法,则调用该方法(没有参数)并返回相应的结果;

  • 若是值是null,则返回"null";

  • 若是值是undefined,则返回"undefined"。

下面看几个例子:

var value1 = 10;
var value2 = true;
var value3 = null;
var value4;

console.log(String(value1));  //"10"
console.log(String(value2));  //"true"
console.log(String(value3));  //"null"
console.log(String(value4));  //"undefined"

3.4.7 Object类型

ECMAScript中的对象其实就是一组数据和功能的集合。对象能够经过执行new操做符后跟要建立的对象类型的名称来建立。而建立Object类型的实例并为其添加属性和方法,就能够建立自定义对象,以下所示:

var o = new Object();

若是不给构造函数传递参数,则能够省略后面的括号,可是这作法不推荐

var o = new Object;  //有效,但不推荐省略圆括号

仅仅建立Object的实例并无什么用处,但关键是要理解一个重要的思想:即在ECMAScript中,Object类型是全部它的实例的基础。换句话说,Object类型所具备的任何属性和方法也一样存在于更具体的对象中。
Object的每一个实例都具备下列属性和方法:

  • constructor:保存着用于建立当前对象的函数。对于前面的例子而已,构造函数(constructor)就是Object();返回一个指向建立了该对象原型的函数引用。该属性的值就是那个函数自己

  • hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在,其中,做为参数的属性名(propertyName)必须以字符串的形式指定例如:o.hasOwnProperty("name");

  • isPrototypeOf(Object):用于检查传入的对象是不是当前对象的原型

  • propertyIsEnumerable(propertyName):用于检查给定的属性是否可以使用for-in语句来枚举。与hasOwnProperty()方法同样,做为参数的属性名必须以字符串形式指定。

  • toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应。

  • toString():返回对象的字符串表示。

  • valueOf():返回对象的字符串、数值、或布尔值表示。一般与toString()方法的返回值相同。
    因为在ECMAScriptObject是全部对象的基础,所以全部对象都具备这些基本的属性和方法。

3.5 操做符

ECMA-262描述了一组用于操做数据值的操做符,包括算数操做符(如加号和减号)、位操做符、关系操做符和相等操做符。ECMAScript操做符的不同凡响之处在于,它们可以使用于不少值,例如字符串、数字值、布尔值、甚至对象。不过在应用于对象时,相应的操做符一般都会调用对象的valueOf()和(或)toString()方法,以便取得能够操做的值。

3.5.1 一元操做符

1.递增和递减操做符
执行前置递增和递减操做时,变量的值都是在语句被求值之前改变的。

var age = 29;
var anotherAge = --age + 2;

console.log(age); //28
console.log(anotherAge);  //30

因为前置递增和递减操做与执行语句的优先级相等,所以整个语句会从左至右被求值。

var num1 = 2;
var num2 = 20;
var num3 = --num1 + num2;//21
var num4 = num1 + num2;  //21

num4相应的加法操做使用了num减去1以后的值

后置递增和递减操做符语法不变,他们的区别就是前置递增和递减被操做时变量的值都是在语句被求值之前改变的。然后置是求值以后才执行的。

把递增操做符放在后面并不会改变语句的结果。

var num1 = 2;
var num2 = 20;
var num3 = num1-- + num2;//22
var num4 = num1 + num2;  //21

递增和递减操做符对任何值都使用,字符串,布尔值,浮点数值,对象

3.5.3 布尔操做符

1.逻辑非
逻辑非操做符由一个叹号( ! )表示,能够应用于ECMAScript中的任何值。不管这个值是什么数据类型,这个操做符都会返回一个布尔值。逻辑非操做符首先会将她的操做数转换为一个布尔值,而后再对其求反。

逻辑非操做符也能够用于将一个值转换为与其对应的布尔值。而同时使用两个逻辑非操做符。实际上就会模拟Boolean()转型函数的行为。其中,第一个逻辑非操做会基于不管什么操做数返回一个布尔值,而第二逻辑非操做则对该布尔值求反,因而就获得了这个值正对应的布尔值。固然,最终的结果与对这个值使用Boolean()相同

2.逻辑与
逻辑与操做符由两个和号(&&)表示,有两个操做数,以下面的例子所示:

var result = true && false;

逻辑与操做能够应用于任何类型的操做数,而不只仅是布尔值。在有一个操做数不是布尔值的状况下,逻辑与操做就不必定返回布尔值;此时它遵循下列规则:

  • 若是第一个操做数是对象,则会返回第二个操做数;

  • 若是第二个操做数是对象,则只有在第一个操做数的求值结果为true的状况下才会返回该对象;

  • 若是两个操做数都是对象,则返回第二个操做数;

  • 若是有一个操做数是null,则返回null

  • 若是有一个操做数是NaN,则返回NaN

  • 若是有一个操做数是undefined,则返回undefined

逻辑与操做属于短路操做,即若是第一个操做数可以决定结果,那么就不会再对第二个操做数求值。对于逻辑与而言,若是第一个操做数是false,则不管第二个操做数是什么值,结果都再也不多是true了。例子:

var found = true;
var result = (found && someUndefinedVariable) //这里会发生错误
alert(result)  这一行不会执行

上面例子发生错误,由于变量someUndefinedVariable没有声明。因为变量found的值是true,因此逻辑与操做符会继续对变量someUndefinedVariable求值。因此逻辑与操做符会继续对变量someUndefinedVariable求值。但someUndefinedVariable没定义因此就致使错误。将found的值设置为false,就不会发生错误了。

3.逻辑或
逻辑或操做符由两个和号(||)表示,有两个操做数,以下面的例子所示:

var result = true || false;

与逻辑与操做类似,若是有一个操做数不是布尔值,逻辑或也不必定返回布尔值;此时它遵循下列规则:

  • 若是第一个操做数是对象,则会返回第一个操做数;

  • 若是第一个操做数的求值结果为false,则返回第二个操做数。

  • 若是两个操做数都是对象,则返回第一个操做数;

  • 若是有两个操做数是null,则返回null

  • 若是有两个操做数是NaN,则返回NaN

  • 若是有两个操做数是undefined,则返回undefined
    与逻辑与操做符类似,逻辑或操做符也是短路操做符。若是第一个操做数的求值结果为true,就不会对第二个操做值求值了,跟逻辑与是相反的。

3.5.6

小于(<)、大于(>)、小于等于(<=)和大于等于(>=)

ECMAScript中的其余操做符同样,当关系操做符的操做数使用了非数值时,也要进行数据转换或完成某些奇怪的操做。一下就是相应的规则。

  • 若是两个操做符都是数值,则执行数值比较;

  • 若是两个操做数都是字符串,则比较两个字符串对应的字符编码值;

  • 若是一个操做数是数值,则另外一个操做数转换为一个数值,而后执行数值比较;

  • 若是一个操做数是对象,则调用这个对象的valueOf()方法,并用获得的结果根据前面的规则执行比较。若是对象没有valueOf()方法,则调用toString()方法,并用获得的结果根据前面的规则执行比较;

  • 若是一个操做数是布尔值,则将他转换为数值,而后执行比较。

任何数与NaN比较都返回false

3.5.7 相等操做符

1.相等和不相等

== 两个数相等 返回true
!= 两个数不相等 返回ture
要比较相等性以前,不能将null和undefined转换成其余任何值。
若是两个操做数都是对象,则比较它们是否是同一个对象,若是两个操做数都指向同一个对象则true,不是则false;

注意:nullundefined是相等的,NaN不等于NaN

2.全等和不全等
全等和相等相似,二者最大区别是全等比较时不转换成数值。
全等和不全等的比较都是在操做数未经转换的状况下比较。

注意:null == undefined返回true,由于他们相似的值;但null === undefined返回false,由于他们是不一样类型的值

3.5.8 条件操做符

variable = boolean_expression ? true_value : false_value;
var max = (num1 > num2) ? num1 : num2;

3.6语句

3.6.1 if语句

if(condition) statement1 else statement2
if(i > 25) {
    alert("Greater than 25.");    
}else{
    alert("Less than of equal to 25.");
}

3.6.2 do-while

var i = 0;
do {
    i+=2;
}while(i < 10);
console.log(i);

3.6.3 while

var i = 0;
while(i < 10) {
    i += 2;
}

3.6.4 for 语句

var count = 10;
for(var i = 10; i < count; i++){
    console.log(i);
}

因为ECMAScript中不存在块级做用于,所以在循环内部定义的变量也能够在外部访问到。

注意:for语句中的初始化表达式、控制表达式和循环后表达式都是可选的。将这三个表达式所有省略,就会建立一个无限循环。

3.6.5 for-in语句

var data = [1,3,2,4,5];
for(var propName in data){
    console.log(data[propName]); //1,3,2,4,5
    console.log(propName); //0,1,2,3,4
}
for(var propName in window){
    console.log(propName); //window对象属性名
}

注意:ECMAScript对象属性没有顺序。所以经过for-in循环输出的属性名的顺序是不可预测的。
注意:建议在使用for-in以前,先检测确认该对象的值不是null或undefined。

3.6.6 label语句

使用label语句能够再代码中添加标签,以便未来使用。

start: for (var i = 0; i < count; i++){
    alert(i);
}

这个例子中定义的start标签能够在未来有breakcontinue语句引用。加标签的语句通常都要与for语句等循环语句配合使用

3.6.7 break和continue语句

break:

var num = 0;
for(var i = 1; i < 10; i++){
    if(i % 5 == 0){
        break;
    }
    num++;
}
console.log(num);  //4

continue:

var num = 0;
for(var i = 1; i < 10; i++){
    if(i % 5 == 0){
        continue;
    }
    num++;
}
console.log(num);  //8

label能够和break和continue:

var num = 0;

outermost:  //循环外标签
for(var i = 1; i < 10; i++){
    for(var j= 0; j < 10; j++){
        if(i == 5 && j == 5){ 
//正常来讲break只能跳出一层循环,但外面使用了label语句的标签outrmost能够直接跳出所有循环到outermost的位置;
            break outermost;
        }
        num++;
    }
}
console.log(num);  //55

3.6.8 with语句

with语句的做用是将代码的做用域设置到一个特定的对象中。with语句的语法以下:

with (expression) statement;

定义with语句的目的主要是为了简化屡次编写同一个对象的工做,以下:

var qs = location.search.substring(1);
var hostName = location.hostname;
var url = localion.href;

上面几行代码都包括location对象。若是使用with语句以下:

width(location){
    var qs = search.substring(1);
    var hostName = hostname;
    var url = href;
}

注意:严格模式不容许使用with语句,会视为语法错误。with语句大量使用会致使性能降低,同时也会给调试代码形成困难,所以在开发大型项目时,不建议使用with语句

3.6.9 switch语句

var num = 25;
switch (true){
    case num < 0:
        console.log("0");
        break;
    case num >= 0 && num <= 10:
        console.log("0");
        break;
    default:
        console.log("0");
}

注意:switch语句在比较值时使用的是全等操做符。

3.7 函数

return语句也能够不带任何返回值。在这种状况下,函数在中止执行后将返回undefined值。

推荐作法:是要么让函数使用都返回一个值,要么永远都不要返回值。不然,若是函数有时候返回值,有时候不反回,会给调试代码带来不便

3.7.1 理解参数

在函数体内可使经过arguments对象来访问这个参数的数组,从而获取传递给函数的每个参数。
经过访问argments对象的length属性能够获知有多少个参数传递给了函数

function doAdd(num1,num2){
    arguments[1] = 10;
    console.log(arguments[1]);        //10
    console.log(num2);                //10
    console.log(arguments[0] + num2); //20
    console.log(arguments.length);    //2  也能够访问arguments对象的length属性能够获取有多少个参数传递给函数
}
doAdd(10,20);

每次执行这个doAdd()函数都会重写第二参数,将第二个参数的值修改成10。由于arguments对象中的值会自动反映到对应的命名函数,因此修改arguments[1],也就修改了num2,结果它们的值都会变成10,不过,这并非说读取这个两个值会访问相同的内存空间;它们的内存空间是独立的,但它们的值会同步。你也能够反过来修改num2的值效果也是同样的。

function doAdd(num1,num2){
    num2 = 10;
    console.log(arguments[1]);        //10
}
doAdd(10,20);

arguments对象能够与命名参数一块儿使用,如:

function doAdd(num1, num2){
    if(arguments.length == 1){
        console.log(num1 + 10)
    }else{
        console.log(argments[0] + num2);
    }
}
  • arguments对象只是与数组相似(它并非Array的实例).

  • arguments的值永远与对应命名参数的值保持同步

  • 没有传递值得命名参数将自动被赋予undefined值。

严格模式下不容许重写命名参数或者arguments的值,虽然能够执行,可是命名参数与arguments对应的值将再也不同步

3.7.2 没有重载

ECMAScript函数没有签名,由于其参数是由包括零或多个值的数组来表示的。而没有函数签名,真正的重载是不可能作到的。

最后,若有错误和疑惑请指出,多谢各位大哥

若是在ECMAScript中定义了两个名字相同的函数,则该名字只属于后定义的函数。

相关文章
相关标签/搜索