从零开始的JavaScript学习之旅——Week 1

199 阅读15分钟

JavaScript概述

什么是JavaScript:简称js,是运行在js解释器解释型、弱类型、面向对象的脚本语言

js解释器

  1. 不需要安装,浏览器自带
  2. 后续在node.js服务器端 - 安装一个独立的js解释器

解释型

  1. 解释型:运行之前不需要检查语法是否正确,直接运行,碰到错误就停止运行,比如:javascript、php...
  2. 编译型:运行之前需要检查语法是否正确,如果不正确,直接不能运行,比如:java、C、C#...

js特点

  1. 代码可用任何编辑器编写

  2. 解释型:不需要检查对错,直接运行,碰到就停止

  3. 弱类型语言:是由数据决定了数据的类型是什么
    1 - number数字
    "1" - string字符串 变量想保存什么数据类型都可以

    注:强类型语言:是由数据类型决定了你要保存的数据是什么

  4. 面向对象语言:万物皆对象(属性和方法)
    语法:对象名.属性名; 对象名.方法名();

js的用途

  1. css能做的,js能做,css不能做的,js也能操作
  2. ajax和服务器端进行交互

js的使用方式

  1. 在HTML页面上写上一个script标签,再在里面编写你的js代码
    <script type="text/javascript">
        //js代码
    </script>
  1. 在外部创建一个.js文件,在里面编写属于你的js代码 - 正式开发中使用
    <script src="js路径" type="text/javascript" charset="utf-8">
	//不能再次编写代码了,必须将js代码放到js文件中
    </script>

注:js都写在html的最后,原因:

  1. 如果js非常的耗时,用户至少能看到html和css的效果
  2. js会操作html结构,如果js放在head中可能找不到元素

js代码

1. 注释

作用:提示自己/别人 - 养成一个写注释的好习惯

  •   单行注释://
    
  •   多行注释:/**/
    

2. 输出方式 - 3种

作用:打桩输出 - 检查错误

  • 在F12的控制台输出日志:console.log(数字/"字符串"/变量); - 这才最重要的(都不会影响到用户的体验)
  • 在页面上输出,支持标签:document.write(数字/"字符串"/变量);
    缺点:如果绑定了一个按钮的事件,替换掉页面上所有的已有元素
  • 在弹出框输出:alert(数字/"字符串"/变量);
    缺点:卡主页面,必须关闭掉弹出框,用户才能看到页面的东西

3. 变量

  • 硬盘:存储文件 数据 - 外部存储器
  • CPU:中央处理器计算
  • 内存:是【临时存储】程序在运行过程中,所需要用到的数据
    内存空间:保存数据的一个地方
    内存地址:内存空间门牌号,0x0132asd123rtsa325sa,内存地址过长,为他取一个别名,就称之为变量名
  • 变量就是一个内存
    语法:var 变量名=值;
    作用:1.  经常使用的数据,可以先提前保存起来
          2.  数据是可能被修改的

注意:

  • 命名规则:
    1. 不能以数字开头
    2. 不能使用关键字
    3. 尽量的见名知意
    千万不要:
       var aa;
       var ab;
       var ac;
    千万不要:
       var xingming; - 逼格低
    尽量要:
       var name;
       var age;
       var gender;
    

变量名有一个很特殊name,不管你保存的数据是什么,最后都会变成一个字符串

  • 创建变量:var 变量名;其实就已经创建好了变量,不赋值也没关系,至少创建不会报错,但是一般来说我们都要立马跟上赋值操作,因为默认值undefined是无用的
  • 如果创建了多个变量,可以省略掉中间var,分号都要换为逗号简写
  • 关键词var可以不写,但是不推荐会导致全局污染
  • =:赋值符号,把=右边的数据保存在=左边的变量名之中,左边就单单纯纯的是一个变量名而已,不会变成变量的值
  • 创建/声明/定义,含义相同
  • null:代表“没有”、“空”

4. 常量

常量一旦创建不可修改,语法:const 常量名=值;

5. 数据类型

数据类型不同,操作不同

  1. 原始/基本/数据类型(5个):
Number - 数字,取值:无数个
String - 字符串,取值:无数个
Boolean - 布尔值,取值:2个,表示一个判断的结果,true(真) false(假)
Undefined - 取值只有一个:undefined(变量的默认值),undefined没有任何作用
Null - 空,取值1个:null,作用:释放内存节约
  1. 引用/对象类型:11个对象(属性和方法)

6. 算术运算符

算术运算符:+-*/%

m%n:取余,俗称模,m/n不取商,而取除不尽的余数
    作用:
        1.  判断奇偶性
            num%2 == 1 奇数
            num%2 == 0 偶数
        2.  获取一个数字的后n位
            1234%10   -> 4
            1234%100  -> 34
            1234%1000 -> 234
        3.  判断一个数字永远不超过几
            num%5 -> 结果永远不会超过5
    注意:算术运算其实具有隐式数据类型转换,默认都会转为数字运算
         +运算,如果碰到一个字符串,那么两边的数据都会转换字符串,然后做拼接操作
         - * / %其实字符串也可以转为数字,必须是纯数字组成的字符串才行,只要包含一个非数字字符结果则为NaN

补充

  1. 用户输入框:var user=prompt("提示文字","默认值");
  2. 查看数据类型:typeof(变量/值/表达式);

数据类型的转换

javascript是弱类型语言,由数据决定了数据类型是什么

对于不同数据类型的运算时,数据类型会自动进行转换:

  • number+number=number
  • number+string=string

隐式转换

隐式转换就是系统默认的、不需要加以声明就可以进行的转换

算术运算符(+-*/%)具有隐式转换——默认两边都转为数字,再运算

注意:

  • +运算,碰上一个字符串,两边都会转为字符串,变为拼接操作
  • - * / % 要是纯数字的字符串也可以转为数字,但是包含了非数字字符则结果为NaN
  • 其他值转为数字的结果
    true->1
    false->0
    undefined->NaN
    null->0
    "100"->100
    "100px"->NaN
  • NaN(Not A Number):不是一个数字,但是确实是number类型(不是有效的数字)
    特点(缺点):1. NaN参与任何算术运算,结果仍为NaN
           2. NaN参与任何比较/关系运算,结果都为false,甚至不认识自己
  • 无法使用普通的关系/比较运算去判断输入是不是NaN
    解决:!isNaN(x); 判断是不是有效数字
    作用:防止无效输入——必须是一个有效数字
    结果:true->是有效数字 ,false->是NaN

显式(强制)转换

隐式转换出来的结果不能达到预期或者要求一定要将某一类型的数据转换为另外一种类型,可以利用强制类型运算符进行转换

1. 转字符串

语法:xx.toString();
注意:undefined和null不支持,undefined和null不能使用“.”操作

2. 转数字

  • 转为整数
    语法:parseInt(str/num);
    执行原理:从左向右依次读取每个字符,碰到非数字字符则停止,并且不认识小数点,如果一来就不认识则为NaN
举例:
    console.log(parseInt(35.45));//35
    console.log(parseInt("35.45"));//35
    console.log(parseInt("3hello5"));//3
    console.log(parseInt("35px"));//35
    console.log(parseInt("hello35"));//NaN
    console.log(parseInt(true));//NaN
  • 转为浮点数(小数)
    语法:parseFloat(str);
    执行原理:从左向右依次读取每个字符,碰到非数字字符则停止,认识第一个小数点,如果一来就不认识则为NaN
举例:
    console.log(parseFloat("35.45"));//35.45
    console.log(parseFloat("35.45.45"));//35.45
    console.log(parseFloat("35.4abc5.45"));//35.4
    console.log(parseFloat("35.45px"));//35.45

以上两个API作用:强制转为数字的同时并且去掉单位

  • 万能转换
    语法:Number(x);
    其实质就是隐式转换,但不如隐式转换简单(*1 /1 -0)

函数(Function)

函数基础

函数(function),也称之为方法

举例
url(图片路径):完成了一个根据图片路径显示图片的功能
rotate(90deg):完成了一个根据角度值顺时针旋转45度的功能
js的自定义函数:完成了一个......功能

函数的定义

函数(Function)是一段被预定义好的,可以反复使用的代码;
函数是个独立的功能体,可以将若干的代码放在里面

语法

  • 创建函数/方法

    function 函数名(){
        //若干代码段
    }
    
  • 调用函数/方法

    函数名();  ——写几次调用几次
    或者绑定在页面元素之上,由用户来触发
    <elem onclick="js语法/函数名();"></elem>
    
  • 函数使用场景

    1. 不希望打开页面立刻执行,等用户来触发
    2. 不希望只执行一次,可以反复触发
    3. 本身就是一个独立的功能体
    4. 建议每一个功能体都要封装为一个函数
      原因:函数在js中具有第一等公民的地位,函数中的变量都是会自动释放的
  • 带有参数的函数

    创建带参数的函数:
        function 函数名(形参,...){//形参(形式参数)其实就是一个变量,只不过不需要var
            函数体;
        }
    调用带参数的函数:
        函数名(实参);//实际参数
    举例:
        榨汁机 - function:功能:榨汁
        原材料 - 参数:放入一个苹果、梨子、香蕉...
        function zzj(fruit){
             console.log("榨"+fruit+"汁");
        }
        zzj("苹果");
        zzj("梨子");
    
    注意:1. 传入实参的顺序一定要和形参的顺序对应上
          2. 函数不一定非要有参数:如果操作是固定的,则不需要传递参数
                                  如果根据传入的实参不同,做的操作略微不同,则需要添加参数
    

分支结构

程序的结构

  1. 顺序结构:默认结构,从上向下依次执行每一句代码
  2. 分支结构:根据判断条件,选择一部分代码去执行(只会走一条路)
  3. 循环结构:根据判断条件,选择是否重复执行某一段代码

比较/关系运算符

比较运算符:> < >= <= == !=
注意:1. 以上六个运算符结果都为布尔值:truefalse
   2. 往往比较运算符出现在分支、循环的判断条件之中
   3. 关系运算符也具有隐式转换

if结构

if选择结构是根据条件判断之后再做处理的一种语法结构
语法:

 1. 一个条件一件事,满足就做,不满足就不做
     if(判断条件){
         操作
     }
 2. 一个条件两件事,满足就做第一件,不满足就做第二件
     if(判断条件){
         操作1
     }else{
         默认操作
     }
 3. 多个条件多件事,满足谁就做谁
     if(条件1){
         操作1
     }else if(条件2){
         操作2
     }else if(条件3){
         操作3
     }else{
         默认操作
     }
注意:1、最后的else是可以省略的,但如果条件都不满足,则分支白写
      2、条件有时候写的顺序需要注意,因为分支只会走一条路

补充

逻辑运算符

&&:与(并且)
    只有全部条件都为true,最后结果才为true
    只要有一个条件为false,最后结果就为false

||:或
    只有全部条件都为false,最后结果才为false
    只要有一个条件为true,最后结果就为true

!:颠倒布尔值:
    !true -> false
    !false -> true

循环结构

循环的定义

循环结构是指在程序中需要反复执行相同或相似的操作而设置的一种程序结构

循环三要素

  1. 循环条件:开始、结束:重复执行的次数
  2. 循环体:循环的操作:要干什么
  3. 循环变量,并且 变量需要不断的变化

while循环

语法:

var 循环变量=几;
while(循环条件){
    循环体;
    循环变量变化一下;
}
执行原理:先判断循环条件,如果条件为真,则执行【一次】循环体
          然后再判断循环条件,如果条件为真,则执行再【一次】循环体
	  ...
	  直到条件为假,循环才会结束
注意:循环是一次一次执行的,并不是同时执行的;
      可以使用break;语句退出循环  ——break;语句出现循环之中

for循环

while能做,for也能做,而且for看上更加的简单/简洁
语法:

for(var 循环变量=几;循环条件;变量的变化){
    循环体
}
注意:for循环变量处其实可以创建多个变量;
      也可以使用break;语句退出循环

死循环

死循环:永远不会结束的循环,但是死循环也是可以退出的
使用场景:不确定要执行的具体次数,往往死循环会搭配上break;进行退出
语法:

while(true){
    循环体
}
或
for(;;){循环体}

数组

数组的定义

  • 定义:多个数据/元素组成的一个集合,保存在一个变量中
  • 特点:数组中的元素都是按照线性顺序来排列,除了第一个元素,每个元素都有一个唯一的前驱元素;除了最后一个元素,每个元素都有一个唯一的后继元素
  • 下标:数组中每个元素都有一个唯一的位置序号,称之为下标,用来表示数组中的每一个元素(注:下标是从0开始,到最大长度-1

创建数组

  1. 直接量方式
var arr=[];//空数组
var arr=[数据,数据,...];
  1. 构造函数方式
var arr=new Array();//空数组
var arr=new Array(数据,数据,...);

访问数组

  1. 获取数据
数组名[下标];
注意:下标越界,获取到的是一个undefined
  1. 添加数据
数组名[下标]=新数据;
注意:1. 如果下标处已有元素,则为替换
      2. 如果下标越界,会导致你的数组变成一个稀疏数组,中间就会出现很多的undefined,而且下标也不再连续
  1. 特点 数组具有3大不限制:
    • 不限制元素的长度
    • 不限制元素的类型
    • 不限制下标越界(但这个操作并不好,强烈不推荐下标越界)

数组唯一属性

获取到数组的长度,语法:数组名.length
三种固定使用方式:

1. 向末尾添加元素:arr[arr.length]=新值;
2. 获取倒数第n个元素:arr[arr.length-n];
3. 删除末尾的n个元素:arr.length-=n;

遍历数组

使用场景:将数组中的每个元素都取出来执行相同相似的操作
语法:

for(var i=0;i<arr.length;i++){
    arr[i];//当前次获取到的元素
}

DOM概述

javascript组成

  1. ECMAScript(ES3/5/6) - 核心语法
  2. DOM - Document Object Model:文档对象模型 - 操作文档(HTML)
  3. BOM - Browser Object Model:浏览器对象模型 - 操作浏览器

DOM概念

DOM树:把HTML看做了是一个倒挂的树状结构,但是树根HTML,而是document对象(document对象不需要程序员创建,由浏览器的js解释器自动创建,一个页面只有一个document)
注意:DOM会把页面上的所有的元素都看做是一个DOM对象(DOM节点/DOM元素)

获取元素

1. 通过 HTML 的属性去获取元素

  • 通过ID获取元素
    语法:var elem=document.getElementById("id值");
    返回:是一个DOM对象/DOM节点/DOM元素,可以直接做操作
    注意:1. 如果id重复了,只会返回第一个
       2. 如果没找到,返回的是一个null
       3. 为给后台预留id,此方法不使用
  • 通过标签名获取元素
    语法:var elems=document/parent.getElementsByTagName("标签名");
    返回:是一个DOM集合(类数组对象),类似数组,也可以使用下标、length、遍历
    注意:1. 一个DOM集合是不允许直接做操作的,除非加下标得到某一个或 遍历得到所有人,才能做操作
       2. 如果没找到,返回的是一个空集合
       3. 此方法不一定非要写document,也可以写一个parent(已经找到的某个父元素)
        如果是写的document,则会找到页面上所有的标签
        而写的是parent,只会找到parent下面的所有的标签
  • 通过class名获取元素
    语法:var elems=document/parent.getElementsByClassName("class名");
    返回:是一个DOM集合(类数组对象),类似数组,也可以使用下标、length、遍历
    注意:1. 一个DOM集合是不允许直接做操作的,除非加下标得到某一个或 遍历得到所有人,才能做操作
       2. 如果没找到,返回的是一个空集合
       3. 此方法不一定非要写document,也可以写一个parent(已经找到的某个父元素)
        如果是写的document,则会找到页面上所有的标签
        而写的是parent,只会找到parent下面的所有的标签

2. 通过节点之间的关系获取元素

前提:至少先要找到一个元素,才能找关系
语法:

1. 父元素:xx.parentNode - 单个元素
2. 子元素:xx.children - 集合
3. 第一个儿子:xx.firstElementChild - 单个元素
4. 最后一个儿子:xx.lastElementChild - 单个元素
5. 前一个兄弟:xx.previousElementSibling - 单个元素
6. 后一个兄弟:xx.nextElementSibling - 单个元素

操作元素

1. 内容:

  • innerHTML:用于操作双标签,能够识别标签
    获取:elem.innerHTML;
    设置/修改:elem.innerHTML="新内容";
  • innerText:用于操作双标签,不能识别标签
    获取:elem.innerText;
    设置/修改:elem.innerText="新内容";
  • value:用于操作input
    获取:elem.value
    设置/修改:elem.value="新内容";

2. 属性:

获取属性值elem.getAttribute("属性名");
设置属性值elem.setAttribute("属性名","属性值");

简化版:获取属性值elem.属性名;
    设置属性值elem.属性名="属性值";

简化版注意:1. class必须写为className
      2. 只能操作标准属性,不能操作自定义属性

3. 样式

操作对象:内联样式
优点:1、优先级最高(保证js用户触发一定会生效)
   2、不会牵一发动全身,只会操作当前元素
缺点:获取样式时,一定要保证此样式在内联样式中

获取样式elem.style.css属性名;
设置样式elem.setAttribute("属性名","属性值");

注意:css属性名的写法,如果有横线要去掉横线,变为小驼峰命名法

举例:
		原来CSS				JS:
		background-color		backgroundColor
		width				width
		border-top-width		borderTopWidth

4.绑定事件

为了保证HTML和CSS和JS分离,不在html中绑定事件

语法:

elem.onclick=function(){
    点击后要执行什么代码
}
补充:
    this关键字:
    单个元素绑定事件,this->这个元素
    多个元素绑定事件,this->当前触发事件的元素