JavaScript基础知识

321 阅读11分钟

1.创建变量的6种方式

变量(variable),它不是具体的值,只是一个用来存储具体指的容器或者代名词,因为它存储的值可以改变,所以称为变量。 基于ES语法,在JS中创建变量有以下方式。

  • var (ES3)
  • function (ES3) 创建函数(函数名也是变量,只不过存储的值是函数类型的而已)
  • let (ES6)
  • const (ES6) 创建的是常量
  • import (ES6) 基于ES6的模块规范导出需要的信息
  • class (ES6) 基于ES6创建类
/*
* 语法:
*    var [变量名] = [值];
*    let [变量名] = [值];
*    const [变量名] = [值];
*    function 函数名() {
*
*    }
*    ...
*/
var n = 13;
n = 15;
alert(n+10); // =>弹出来25,此时n代表15

const m = 100;
m = 200; // Uncaught TypeError:Assignment to constant variable.不能给一个常量重新的赋值(常量存储的值不能被修改,能被改变的就是变量了)

2.JS中的命名规范

  • 严格区分大小写
  • 遵循驼峰命名法: 按照数字、字母、下划线来命名(数字不能作为名字的开头),命名的时候基于英文单词拼接成一个完整的名字(第一个单词字母小写,其余每一个有意义的单词的首字母都大写)
  • 不能使用关键字和保留字(在JS中有特殊含义的叫做关键词,未来可能会成为关键字的叫做保留字)
var n = 12;
var N = 13; //=>两个n/N不是同一个变量

var studentInfo / student_info / _studentInfo(下划线在前面的,都是公共变量) / $studentInfo(一般存储的是JQ元素) ...

语义化强一些
  add / create / insert / delete / update / remove / info / detail / log

3.数据类型的分类

数据值是一门变成语言进行生产的材料,JS中包含的值有以下这些类型

  • 基本数据类型(值类型)
    • 数字 number
    • 字符串 string
    • 布尔 boolean
    • null
    • undefined
  • 引用数据类型
    • 对象 object
      • 普通对象
      • 数组对象
      • 正则对象
      • 日期对象
      • ...
    • 函数 function
  • ES6中新增加一个特殊的类型:Symbol,唯一的值
[基本数据类型]
var n = 13; // => 0 -13 13.2  数字类型中有一个特殊类型的值 NaN(not a number代表不是一个有效的数字,但是属于number类型的)

var s = ''; //=>"" '13' "{}" JS中所有用单引号或者双引号包裹起来的都是字符串,里面的内容是当前字符串中的字符(一个字符串由零到多个字符组成)

var b = true; //=>布尔类型只有两个值 true真 false假

[引用数据类型]
var o = {name: 'zfpx', age: 9}; //=>普通的对象:由大括号包裹起来,里面包含多组属性名和属性值(包含多组键值对) {} 空对象

var ary = [12,23,34,45]; //=>中括号包裹起来,包含零到多项内容,这种是数组对象。  [] 空数组

var reg = /-?(\d|([1-9]\d+))(\.\d+)?/g; //=>由元字符组成一个完整的正则

function fn () {

}

[Symbol]
创建出来的是一个唯一的值
var a = Symbol('珠峰');
var b = Symbol('珠峰');
console.log(a == b); // false

JS代码如何被运行以及运行后如何输出结果 [如何被运行]

  • 把代码运行在浏览器中(浏览器内核来渲染解析)
  • 基于NODE来运行(NODE也是一个基于V8引擎渲染和解析JS的工具) [如何输出结果]
  • alert: 在浏览器中通过弹框的方式输出(浏览器提示框)
var num = 12;
alert(num); //window.alert

var str = 'zfpx';
alert(str);

基于alert输出的结果都会转化为字符串:把值(如果是表达式先计算出结果)通过toString这个方法转换成字符串,然后再输出
alert(1+1); // '2' 
alert(true); //=> 'true'
alert([12,23]); // => '12,23'
alert({name:'xxx'}); //[Object Object] 为啥?
  • confirm: 和alert的用法一致,只不过提示的框中有确定和取消两个按钮,所以它是确认提示框
var flag = confirm('确定要退出吗');
if (flag) {
    //=>flag:true 用户点击的是确定按钮
} else {
    // false 用户点击的是取消按钮
}
  • prompt: 在confirm的基础上增加输入框
  • console.log: 在浏览器控制台输出日志
    • Elements: 当前页面中的元素和样式在这里都可以看到,还可以调节修改结构等
    • Console: 控制台,可以在JS代码中通过.log输出到这里,也可以在这里直接的编写JS代码
    • Sources: 当前网站的源文件都在这里 ...
  • console.dir: 比log输出的更加详细信息一些(尤其是输出对象数据值的时候)
  • console.table: 把一个JSON数据按照表格的方式输出 — ... (自己回去扩展更多的console输出的方法)

4.number数据类型详细解读(NaN和isNaN)

  • number数字类型 NaN: not a number 但是它是数字类型的 isNaN: 检测当前值是否不是有效数字,返回true代表不是有效数字,返回false是有效数字
//=> 语法:isNaN([value])
var num = 12;
isNaN(num); //->检测num变量存储的值是否为非有效数字 false

isNaN('13')  => false
isNaN('珠峰') => true
isNaN(true) => false
isNaN(false) => false
isNaN(null) => false
isNaN(undefined) => true
isNaN({age:9}) => true
isNaN([12,23]) => true
isNaN([12]) => false
isNaN(/^$/) => true
isNaN(function() {}) => true

// isNaN检测的机制
1、首先验证当前要检测的值是否为数字类型,如果不是,浏览器会默认的把值转换成数字类型

把非数字类型的值转换为数字
- 其他基本类型转换为数字:直接使用Number这个方法转换的

[字符串转数字]
Number('13') -> 13
Number('13px') -> NaN 如果当前字符串中出现任意一个非有效数字字符,结果为NaN
Number('13.5') -> 13.5 可以识别小数

[布尔转数字]
Number(true) -> 1
Number(false) -> 0

[其它]
Number(null) -> 0
Number(undefined) -> NaN

- 把引用数据类型转换为数字:先把引用值调取toString转换成字符串,然后再把字符串调取Number转换为数字


2、当前检测的值已经是数字类型,是有效数字返回false,不是返回true(数字类型中只有NaN不是有效数字,其余都是有效数字)

5.布尔类型和null以及undefined

布尔类型:只有两个值 true / false

如何把其他数据类型转换为布尔类型

  • Boolean
  • !
  • !!
Boolean(1) -> true
Boolean(0) -> false
Boolean(-1) -> true
Boolean(NaN) -> false

!'珠峰' => 先把其它数据类型转换为布尔类型,然后再取反

!!null => 取两次反,等价于没取反,也就剩下转换为布尔类型了

规律:在JS中只有"0,NaN,"",null,undefined"这5个转换为布尔类型是false,其余都转换为true

null && undefined

都代表空

  • null: 空对象指针
  • undefined: 未定义

null一般都是意料之中的没有(通俗理解:一般都是人为手动的先赋值为null,后面的程序中我们会再次给他赋值)

var num = null; // =>null是手动赋值,预示着后面我会把num变量的值进行修改
...
num = 12;

undefined代表的没有一般都不是人为手动控制的,大部分都是浏览器自助为空(后面可以赋值也可以不赋值)

var num; // =>此时变量的值浏览器给分配的就是undefined
...
后面可以赋值也可以不赋值

6.对象数据类型的常规操作

普通对象

  • 由大括号包裹起来的
  • 由零到多对数星星和属性值(键值对)组成 属性是用来描述当前对象特征的,属性名是当前具备这个特征,属性值是对这个特征的描述(专业语法,属性名称为键[key],属性值称为值[value],一组属性名和属性值称为一组键值对)
var obj = {
    name: "珠峰",
    age: 9
}
//=>对象的操作:对键值对的增删改查

[获取]
语法:对象.属性名  / 对象[属性]
obj.name
obj['name']  一般来说,对象的属性名都是字符串格式的(属性值不固定,任何格式都可以)

[增/改]
JS对象中属性名是不允许重复的,是唯一的

obj.name = 'zfpx'; //=>原有对象中存在name属性名,此处属于修改属性名
obj.sex = '男'; //=>原有对象中不存在sex,此处相当于给当前对象新增加一个属性sex

obj['age'] = 28; // =>修改属性

[删]
彻底删除: 对象中不存在这个属性了
delete obj['age'];

假删除: 并没有移除这个数属性,只是让当前属性的值为空
obj.sex = null;

在获取属性值的时候,如果当前对象有这个属性名,则可以正常获取到值(哪怕是null),但是如果没有这个属性,则获取的结果是undefined
obj['friends'] => undefined

[思考题]

var obj = {
    name: '珠峰',
    age: 9
};
var name = 'zhufeng';
console.log(obj.name); // '珠峰'
console.log(obj['name']); // '珠峰'
console.log(obj[name]); // =>此处的name是一个变量,我们要获取的属性名不叫name,是name存储的值'zhufeng' obj['zhufeng'] =>没有这个属性,属性值是 undefined
---------
'name' 和 name 的区别?
  => 'name'是一个字符串值,它代表的事本身
  => name是一个变量不是值,它代表的是本身存储的这个值 

一个对象中的属性名不仅仅是字符串格式的,还有可能是数字格式的

var obj = {
    name: '珠峰',
    0: 100
};
obj[0] => 100
obj['0'] => 100
obj.0 => Uncanght SyntaxError: Unexpected number

-------
当我们存储的属性名不是字符串也不是数字的时候,浏览器会把这个值转换为字符串(toString),然后再进行存储

obj[{}]=300; =>先把{}.toString()后的结果作为对象的属性名存储起来 obj['[object Object]']=300

obj[{}] => 获取的时候也是先把对象转换为字符串 '[object Object]',然后获取之前存储的300

----
数组对象(对象是由键值对组成的)
var oo = {
    a: 12
}
var ary = [12,23]; //=>12和23都是属性值,属性名呢?

通过观察结果,我们发现数组对象的属性名是数字(我们把数字属性名称为当前对象的索引)
ary[0]
ary['0']
ary.0 => 报语法错误

7.浅聊JS的运行机制(堆栈内存和不同数据类型操作方式)

var a = 13;
var b = a;
b = 13;
console.log(a);

var obj1 = {n: 100};
var obj2 = obj1;
obj2['n'] = 200;
console.log(obj1.n);

/**
* 浅分析JS的运行机制
*   1、当浏览器(它的内核\引擎)渲染和解析JS的时候,会提供一个供JS代码运行的环境,我们把这个环境称之为"全局作用域(global scope)"
*   2、代码自上而下窒息性(之前还有一个变量提升阶段)
*   var a = 12;
*   1)首先开辟一个空间存储12
*   2)在当前作用域下声明一个变量a (var a)
*   3)让声明的变量和存储的12进行关联(把存储的12赋值给a=>赋值操作叫做定义)
*   
*   基本数据类型(也叫做值类型),是按照值来操作的:把原有的值复制一份,放到新的空间或者位置上,和原来的值没有关系
*
*   => 引用数据类型的值不能直接存储到当前的作用域下(因为可能存储的内容过于复杂),我们需要先开辟一个新的空间(理解为仓库),把内容存储到这个空间中
*   var obj1 = {n: 100};
*   1)首先开辟一个新的内存空间,把对象中的键值对依次存储起来(为了保证后面可以找到这个空间,此空间有一个16进制的地址)
*   2)声明一个变量
*   3)让变量和空间地址关联在一起(把空间地址赋值给变量)
*
*   引用类型不是按照值来操作,它操作的是空间的引用地址:把原来空间的地址赋值给新的变量,但是原来的空间没有被克隆,还是一个空间,这样就会出血线多个变量关联的事相同的空间,相互之间就会存在影响了。
*   栈内存:本身就是一个供JS代码执行的环境,所有的基本类型值都会直接在栈内存中开辟一个位置进行存储
*   堆内存:用来存储引用类型中的信息值的,对象存储的是键值对,函数存储的是代码字符串
*/

var obj = {
    n: 10,
    m: obj.n * 10
}
console.log(obj.m); //=>Uncaught TypeError: Cannot read property 'n' of undefined
/**
*   1、形成一个全局作用域(栈内存)
*   2、代码自上而下执行
*     1.首先开辟一个新的堆内存(AAAFFF111),把键值对存储到堆内存中
*       n:10
*       m:obj.n*10 =>obj.n 此时堆内存信息还没有存储完成,空间的地址没有给obj,此时的obj是undefined, obj.n<=>undefined.n
*/

var ary1 = [3,4];
var ary2 = ary1;
ary2[0] = 1;
ary2 = [4,5];
ary2[1] = 2;
ary1[1] = 0;
console.log(ary1,ary2);  // [1, 0], [4, 2]

8.JS中的判断操作语句

  1. if / else if / else
var num = -6;
if (num>10) {
    num++; // num=num+1 num+=1 在自身的基础上累加1
}else if (num>=0 && num<=10) {
    num--;
}else{
    num+=2;
}
console.log(num); // -4

只要有一个条件成立,后面不管是否成立的条件,都不再判断执行了

var num = 10;
if (num>5) {
    num+=2;
}else if(num>8) {
    num+=3;
}else{
    num+=4;
}
console.log(num);  // 12

关于条件可以怎么写?

//  >=  <=   ==
if (0) {
    //=>不管你在条件判断中写什么,最后总要把其计算出true/false来判断条件是否成立(把其他类型的值转换为布尔类型,只有 0/NaN/''/null/undefined 是false,其余都是true)
}

if('3px'+3) {
    //=>在JS中,+ - * / % 都是数学运算,除 + 以外,其余运算符在运算的时候,如果遇到了非数字类型的值,首先会转换为数字类型(Number),然后再进行运算
}

    //=>+在JS中出了数学相加,还有字符串拼接的作用(如果运算中遇到了字符串,则为字符串拼接,而不是数学相加)
var num = parseInt('width:35.5px');
if(num==35.5) {
    alert(0);
}else if(num==35) {
    alert(1);
}else if(num==NaN){
    alert(2);
}else if(typeof num=='number') {
    //=>先算typeof num
    //=>再做比较
    alert(3); //=>alert输出的都是字符串格式的 ‘3’
}else{
    alert(4);
}

9.三元运算符和switch case

1、三元运算符 语法:条件?成立做的事情:不成立做的事情;<=> 相当于简单的if/else判断

var num = 12;
if (num>10) {
    num++;
}else{
    num--;
}
// num>10?num++:num--;

特殊情况

//=>如果三元运算符中的某一部分不需要做任何的处理,我们用null/undefined/void 0...占位即可
var num = 12;
num>=10?num++:null;

//=>如果需需要执行多项操作,我们把其用小括号括起来,每条操作语句用逗号分隔
num = 10;
num>=10?(num++,num*=10):null;

[思考题]:改成三元运算符

var num = 12;
if (num>0) {
    if(num<10) {
        num++
    }else{
        num--;
    }
}else{
    if(num==0) {
        num++;
        num=num/10;
    }
}

2.switch case JS中的一种判断方式

var num = 12;
if (num==10) {
    num++;
}else if(num==5){
    num--;
}else{
    num=0
}
//=>改成switch case
switch(num) {
    case 10:
        num++;
        break;
    case 5:
        num--;
        break;
    default:
        num=0;
}

//=>switch case 应用于变量(或者表达式等)在不同值的情况下的不同操作,每一种case结束后都要加break(结束整个判断)

switch case中每一种case情况的比较都是基于"==="绝对相等来完成的
'10'==10 =>true 相等比较,如果等号左边两边的类型不一样,首先会转换为一样的额数据类型,然后再进行比较
=>当前案例中,就是把字符串'10'转换为数字了,然后再比较的
'10'===10 绝对比较,如果两边的数据类型不一样,则直接不相等,它要求类型和值都完全一样才会相等(真实项目中为了保证代码的严谨性,我们应该更多使用绝对比较)

var num = 12;
switch(num) {
    case 10:
    case 5:
        num--;
        break;
    default:
        num=0;
}
//=>不加break,后面的条件不管是否成立,都会被执行;利用此机制,我们可以完成一些特殊的处理,例如:如果num等于10和等于5都要做同一件事情,那么我们写在一起,不用加break即可

10.for循环的基础运行机制

1、for循环

作用:按照一定的规律重复去做某件事情,此时我们就需要使用循环来处理了。

var ary = [12,23,34];
/**
* 循环输出数组中的每一项内容
*/
for (var i = 0; i < ary.length; i++) {
    //=>第一次循环:i=0 i<3 ... i=1
    //=>第一次循环:i=1 i<3 ... i=2
    //=>第一次循环:i=2 i<3 ... i=3
    //=>第一次循环:i=3 i<3 循环结束(本次没有循环)
    console.log(ary[i]);
}
/**
* for循环的语法组成
*    1.定义初始值  var i = 0;
*    2.设定循环成立的条件(条件成立循环继续,不成立循环结束) i < ary.length
*    3.条件成立会执行循环体中的内容(大括号包裹的就是循环体)
*    4.执行步长累加的操作
*/

// 倒着输出 34 23 12
// =>ary.length-1:当前数组中最后一项属性名(索引)
for (var i = ary.length - 1;i >= 0;i--) {
    console.log(ary[i]);
}

// 输出数组中的内容:输出奇数项的内容
for (var i = 0; i < ary.length; i++) {
    if (i % 2 === 0) {
        console.log(ary[i]);
    }
}
for (var i = 0; i < ary.length; i+=2) {
    console.log(ary[i]);
}
for循环的循环体中,经常出现两个常用的关键字:
/**
*    1.continue:继续
*    2.break: 中断或者结束
*/