前端视频学习(四、JavaScript基础)

JS课程安排:

  1. JS基础 :6天
  2. WebAPI: 6-7天
  3. JS高级:5天
  4. jQuery:5天

JS基础:

  1. 基本介绍、语法、变量、数据类型、运算符
  2. 条件、循环
  3. 数组、函数
  4. 函数——作用域、预解析
  5. 创建对象、数据类型深入、内置对象
  6. 内置对象和方法

目录

1. 简介

Brendan Eich 在95年花了10天时间设计出了JavaScript,并且因为它不喜欢Java,所以也不喜欢JavaScript

1.1 JS分三个部分:

  1. ECMAScript 标准——基本语法
  2. DOM——Document Object Model
  3. BOM—— Browser Object Model

在这里插入图片描述

1.2 JS能做的东西:

  1. 网页特效
  2. 服务端开发 node.js
  3. 命令行工具 node.js
  4. 桌面 Electron
  5. App Cordova
  6. 控制硬件-物联网 Ruff
  7. 游戏开发 cocos2d-js

1.3 JavaScript语言特点

  1. 脚本语言
  2. 解释性语言
  3. 动态类型语言
  4. 基于对象的语言

1.4 Js代码书写位置

  1. 在script标签中
<script>
	alert('haha');
</script>
  1. 写在html标签中
<button onclick="alert('abc');" />
  1. **在外部.js文件中,由html文件引入: **
<script src="demo.js" ></script>

1.5 js代码的注意问题

  1. 在一对script标签中有错误的代码,后面的代码也不会执行
  2. 一对script标签的错误,不会影响其他script标签中的代码执行;
  3. script标签中,本来要写 type="text/javascript"或者language="JavaScript",但是html5标准中可以省略
  4. typelanguage也可以同时写在script
  5. script标签在页面中可以出现多个
  6. script标签的位置一般放在<body>内部的最后端,有时会放在head中
  7. 如果一个script标签的作用是引入外部的js文件,那么这个script标签中不要写代码

WebStorm不是直接打开文件显示的,而是自己以一个小型服务器的方式浏览页面


2. 变量

2.1 变量声明初始化

a. 基本代码规范:

  1. JS变量区分大小写
  2. 声明变量使用var
  3. 字符串使用单引号或者双引号
  4. 语句用分号结尾

b. 变量名规范:

  1. 一般以字母,$,下划线,数组组成,但不能以数字开头
  2. 变量名一般小写
  3. 使用camelCase方式命名
  4. 不能使用关键字
  5. 第二次初始化同一个变量名,则初始化会变成赋值

c. 声明+初始化:

var num = 10;
var num1, num2, num3;
var num1, num2, num3 = 10;
var num1=10, num2 = 10, num3 = 20;
var num1 = num2 = num3 = 30;


var name = '小黑';   // 字符串使用 " 或者 ' 
var flag = true;
var obj = null;
console.log(flag);

2.2 代码注释

// 单行注释

/* 
	多行注释
*/


/**
* 这是说明这个函数是干什么的
* @param param1 这里说明这个param1参数是干什么的
* @return {}  这里说明返回值是个什么
* */

2.3 变量类型

a. 原始数据类型:

  1. number: 整数和小数都是 number 类型, NaN也是number类型
  2. string
  3. boolean
  4. null类型还是 object
  5. undefined : 变量声明没赋值、 函数没有返回值确赋值给了一个变量; undefined 和数字运算,结果为 NaN,也是number类型
  6. object

b. 查看变量类型:

typeof(变量);
typeof 变量;
// number string boolean object undefined object function

c. 进制表示

十六进制: 0x
八进制: 0

d. 数字类型

数字最大最小值

Number.MAX_VALUE
Number.MIN_VALUE
Infinity    // 无穷大
-Infinity   //无穷小

不要用小数和小数相等

(0.1+0.2) == 0.3   // false

和NaN比较

  • 数字和undefined运算,结果是NaN,类型为number;
  • 数字和NaN运算,结果是NaN,类型为number
  • 使用isNaN判断
  • isNaN不光能用来判断NaN,主要可以判断是不是数字
var num;
typeof (num+10);   // number---NaN
num+10 == NaN;  // false  , NaN之间用 == 比较都是false

// 使用 isNaN判断
isNaN(10);    // NaN != NaN

e. 字符串

长度

// 长度
var strvar = "hahsasdsad";
strvar.length

拼接

  1. 加法中有一个是字符串,则会转变成字符串拼接
  2. 如果使用了减法、乘法、除法,则会尝试将字符串变成数字后运算。如果转换失败,则返回NaN
// 拼接:
str3 = str1 + str2
console.log(10+"20");   // 1020
console.log(10-"20");   // -10
console.log(10 * "5");   // 50

2.4 ★类型转换

其他类型转数字:

parseInt("10");   //10  
parseInt("10asdasdasd");   //10
parseInt("10.98");   //10
parseInt("asd10");   //NaN
parseFloat("10")   //10
parseFloat("10asdasd")   //10
parseFloat("10.98")   //10.98
parseFloat("10.98asdsad")   //10.98
parseFloat("asd10asdasd")   //NaN

Number就是转数字, 和parse不同,它需要全部都是数字,更加严格

Number("10");   //10
Number("10asdasd");  //NaN
Number("10.98");   //10.98
Number("10.98asdsad"); //NaN
Number("asd10asdasd");  //NaN

其他类型 转字符串:

第一种:(要变量有意义,比如不能为 undefined, null

num.toString();     //变量无意义,则无法使用 toString()

第二种:

String(var);

第三种:

var + '';

其他类型转boolean:

Boolean(var):
1       true
0       false
11      true
-10     true
"hah"   true
""      false
null    false
undefined false

3. 操作符

  • 算数运算符: + - * / % ( python没有整除,需要用 parseInt来取整)
  • 一元运算符: ++ --
  • 二元运算符:
  • 三元运算符: ?:
  • 赋值运算符: += -= /= %= *=字符串和数字比较的时候会有类型转换)
  • 关系运算符:> >= < <= == === != !===
==  不严格的等于:
var str = "5";
var int = 5;
str == int ; // true

=== 严格的等于:
str === int ; // false
  • 逻辑运算符: && || !
var a = null;
// 没报错,短路比较
if(a != null && a.length > 5){
    alert(a.length);
}

算术运算表达式
关系运算表达式
逻辑运算表达式

优先级

优先级从高到底
	1. ()  优先级最高
	2. 一元运算符  ++   --   !
	3. 算数运算符  先*  /  %   后 +   -
	4. 关系运算符  >   >=   <   <=
	5. 相等运算符   ==   !=    ===    !==
	6. 逻辑运算符 先&&   后||
	7. 赋值运算符

4. 条件

if (条件){    // 条件部分会被转换成 Boolean
}

if(){
} else{
}

if(){

} else if(){

} else{

}

//三元表达式
let result = a?b:c;


// switch判断
switch (key) {
    case value:
        //代码..
        break;

    default:
        break;
}

switch 注意事项

switch内部的比较是使用的===,判断类型+内容,而不是==

var age = "10"
switch (key) {
    case 10:
        ..
        break;

    case "10":
        console.log("字符串10");    // 会执行这一句
        break;
}

5. 循环

document.write()写到HTML文档中的东西,在源代码中看不到,而在调试窗口的element能看到。

  • while
  • do-while
  • for
  • continue, break
while (condition) {
	语句    
}


do {
    语句
} while (condition);


for (let index = 0; index < array.length; index++) {
    const element = array[index];    
}


for in

for of

a.foreach

6. 数组

6.1 创建数组

  1. 通过构造函数
var ar = new Array();   // 构造函数创建空数组

var ar = new Array(5);   // 创建长度为5的数组, 每个元素都是 undefined

var ar = new Array(1,2,"3",new Object());   // 直接传入内容

console.log(arra.length);
  1. 通过字面量
var ar = [];   //字面量创建

数组特点

  1. 使用长度的方式创建数组,数组内部的值都是undefined
  2. 数组可以存储不同类型内容
  3. 可以动态给数组的任意索引赋值,这能改变数组长度,并且没有值的都是undefined

6.2 动态改变数组长度

var ar = [];
alert(a.length);  // 0

ar[1] = ""; 
alert(a.length);  // 2

a[2] ;     //undefined  不存在的值会undefined

6.3 遍历


for(let i = 0; i < a.length; i++){
	
}

a.forEach(element => {
      console.log(element);  
    });


for (const iterator of a) {
    console.log(iterator);
}

7. 函数

7.1 函数定义

function funcname(arg1, arg2){
    ...
    return result;
}

Math.PI

★函数的注意问题:

  1. 函数一旦重名(多次定义),后面的会覆盖前面的函数
function f1(){
    console.log('1');
}
f1();
function f1(){
    console.log('2');
}
f1();
// 结果会打印2次 2
  1. 形参的个数和实参的个数可以不一致(可多可少), 没有传递的值或者接收了没有return的函数值,结果是undefined
function haha(x,y) {

        console.log(x);
        console.log(y);
        console.log(arguments.length);
}

haha();   // undefined  undefined  0
haha(1,2,3);   // 1  2   3
  1. 直接输出函数名字,结果为函数的代码

7.2 函数的参数和返回值

a. 返回值问题

  • 如果没有return,函数返回值为undefined
  • 如果return后面没有内容,则返回值也是undefined

b. arguments

arguments是一个伪数组

function funcname(x, y){
    console.log(arguments); // 获取所有传入的参数  arguments.length
}

7.3 命名函数和匿名函数

函数有名字就是命名函数,没名字就是匿名函数

function(){
	// 这是匿名函数
}


function f1(){
	// 这是匿名函数
}

函数自调用——匿名函数直接调用

(function (){

})()

7.4 ★函数声明和函数表达式

  • 函数能够调用,是因为函数名存储的函数的代码:
  • 如果函数能被调用,则调用方式为: 函数的代码();

1. 函数声明

function f1(){

}
f1();   // 函数代码();  

2. 函数表达式

函数表达式后面要加分号

var f2 = function (){

};
f2();

3. 函数表达式的覆盖问题

函数声明重名的,后面覆盖前面的,导致前面的失效; 而函数表达式,只有在赋值的时候,才会覆盖:

function f1(){
    console.log('1');
}
f1(); // 2
function f1(){
    console.log('2');
}
f1(); // 2
f2 = function (){

}
f2();
// 1 
f2 = function (){
    console.log('2');
}
f2();
// 2

7.5 函数作为参数和返回值

函数作为参数,叫做回调函数

typeof f1   // function

function f1(f2){
    f2();
}
function f2(){

}

作为返回值:

function f3(){
    return function(){
        console.log();
    }
}
fn = f3();
fn();

7.6 ★作用域

1. 跨越script标签

跨越script标签,也可以引用:

<script>
	var num = 10;
	console.log(num);  // 10
</script>
<script>
	console.log(num);  // 10
</script>

2. 块级作用域

在没有let之前,js没有块级作用域

{
	var num = 10;
}	
console.log(num);  // 10

使用let定义的,才是块级作用域; 用var的话,没有块级作用域

3. 全局变量

  • var在函数外面声明的变量是全局变量
  • 除了函数内部定义的, 其他定义的都是全局变量(除了let)

4. 局部变量

函数内部定义的是局部变量, 只在函数内部有效

5. 隐式全局变量

  • 声明变量没有使用var,叫作隐式全局变量
  • 隐式全局变量定义在函数中,外面也能访问
  • 定义变量使用var是不会被删除的,没有使用var是会被删除的
var num1 = 10;
num2 = 20;
delete num1;
delete num2;
console.log(typeof num1);  // number
console.log(typeof num2);  // undefined

6. 作用域链

  • 标签内定义的叫做0级作用域
  • 0级作用域定义的函数内部,叫做1级作用域
  • 函数最内层查找变量的顺序,是 N级–> … --> 3级–> 2级–>1级–>0级

下面的num,会一层层向上找,直到找到

var num = 10;
function f1(){
    var num = 20;
    function f2(){
        var num = 30;
        function f3(){
            var num = 40;
            console.log(num);
        }
        f3();
    }
    f2();
}
f1();

7.5 ★★预解析

JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的。JavaScript解析器执行JavaScript代码的时候,分为两个过程:

  1. 预解析过程
  2. 代码执行过程
  1. 把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值。
  2. 把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用。
  3. 先提升var,在提升function
  4. 变量提升
    定义变量的时候,变量的声明会被提升到作用域的最上面,变量的赋值不会提升。
  5. 函数提升
    JavaScript解析器首先会把当前作用域的函数声明提前到整个作用域的最前面

特点

  1. 浏览器把变量、函数的声明提前了,提前到当前作用域的最上面,不会提升到作用域之外
  2. 多对<script>之间的预解析不会冲突——只会在各自范围内进行预解析
  3. 先提升var再提升function,即 var在function之前
  4. 函数表达式不会提升

例子

例1——预解析提前 变量声明

console.log(num);       // 结果为 undefined,代表变量声明了但是没赋值
var num = 10;     

例2——预解析提前函数声明

f1()   // 调用成功,说明函数声明被提前了
function f1(){
	console.log("haha")   
}

例3——num提前到作用域内部的顶端

var num = 20;
function f1(){
    console.log(num);   // 结果为undefined, 说明 内部的num被提升到了 f1内部作用域的顶端
    var num = 10;
}
f1();

//相当于:
var num = 20;
function f1(){
	var num;
	console.log(num);
	num = 10;
}

例4:

f1();                 // 打印 undefined
var num = 20;
function f1(){
    console.log(num);   
}

// 相当于:
var num;
function f1(){
	console.log(num);
}
f1();   // 所以是undefined
num = 20;

例5——预解析不会把变量提升到函数外

function f1(){
	console.log(num);  // undefined
	var num = 10;
}
f1();
console.log(num);  // 报错

//相当于
function f1(){
	var num;
	console.log(num);
	num = 10;
}
f1();
console.log(num);

例6:——预解析只在script标签内部(同一个全局作用域内)

<script>
f1();   // 1
function f1(){
	console.log("1");
}
</script>

<script>
function f1(){
	console.log("1");
}
</script>
<script>
function f1(){
	console.log("1");
}
</script>

<script>
f1();   // 2
function f1(){
	console.log("1");
}
</script>

例7:

console.log(a);    // 易错点:输出函数代码
function a(){               
    console.log('hahaha');
}
var a = 1;   
console.log(a);     // 输出1

// 相当于
var a ;
function a(){...}  // 此处a就变成了代码
console.log(a);
a = 1;
console.log(a);

例8:—— 隐式全局变量的提升

f1();
console.log(c);    // 9
console.log(b);     // 9
console.log(a);     // 报错
function f1(){
    var a = b= c = 9;    //易错点
    console.log(a);
    console.log(b);
    console.log(c);
}

//提升后为:
function f1(){
    var a;  //局部变量
    a = 9;
    b = 9;  //隐式全局变量
    c = 9;  //隐式全局变量
    console.log(a);
    console.log(b);
    console.log(c);
}
f1();
console.log(c);
console.log(b);
console.log(a);

例9——函数表达式不会提升

f1();       //无法调用, 因为函数表达式不会提升, 只提升函数定义
var f1 = function(){
    console.log(a);
    var a = 10;
}

// 提升后为:
var f1;
f1();
f1 = function(){...};

8. 对象

  • JS本来没有类的概念,只有对象。
  • JS是基于对象的语言——万物皆对象,而不是真正的面向对象的语言,但是可以模拟面向对象

  • 判断对象类型: 变量 instanceof 类型
  • 访问自己对象的属性/方法: this

8.1 创建对象

1. 通过调用系统的构造函数创建

new Object()

var obj = new Object();
// 添加属性和方法
obj.age = 18;
obj.name = "foo";
obj.eat = function(){
    this.age ...            //当前对象中使用 this关键字
};

1b 工厂方法创建对象

function createPeople(name, age){
	var person =  new Object();
	person.name = name;
	person.age = age;
	person.sayHi = function(){
	
	};
}

2. 自定义构造函数创建

Object是系统构造函数,系统定义方式为:

function Object(value){}

使用构造函数. 和普通函数的区别就是名字开头是否大写

function Person(name, age){       
    this.name = name;
    this.age =  age; 
    this.sayHi = function(){
        console.log(this.name);
    }
}
var obj = new Person('haha',18);
obj instanceof Person

创建对象经历的事情:

  1. 在内存中申请一块空闲的空间,创建对象
  2. this设置为当前对象
  3. 设置对象属性和方法
  4. 返回this对象

3. 字面量形式创建

var obj = {};
obj.name = "";
obj.sayHi = function(){
	console.log(this.name):
}

var obj = {
    name: "小明",
    age: 20;
    sayHi: function(){

    },
    eat: function(){

    }
};

8.2 获取和设置对象的属性、方法—— .[]

以某个变量值当做属性名来访问,就只能使用[]

obj.属性名    // 不管有没有,都能 点出来,点出来是 undefined
obj["属性名"]  = 值

obj.plary();
obj['play']();

8.3 Json

  1. 对象:是 属性与方法的集合
  2. 对象:也是一组无序属性的集合,属性的值可以是任意类型

json: 键/值 都用双引号括起来

var json = {
    "name":"ab",
    "age" : "18",
    "sex": "male"
}
json.ddsdsd      // 能点出来,但是没有的属性,都是 undefined

json.name
json["name"]


// 遍历对象
for(var key in obj){
    console.log(key);    // 遍历对象的属性
    console.log(obj[key]);    // 注意不要使用 obj.key,这就成了访问 'key'这个属性了
}

8.4 JS的数据类型

原始数据类型: number, string, boolean, undefined, null, object:

  • 基本类型(简单),值类型: number, string, boolean
  • 复杂类型(引用):object
  • 空类型: undefined, null
var num1 = 66;
var num2 = 88;

function f1(num, num1) {
	num = 100;
	num1 = 100;
	num2 = 100;
	
	console.log(num1);
	console.log(num2);
	console.log(num);
}

f1(num1, num2);

console.log(num1);
console.log(num2);
console.log(num);		

9. 内置对象

JS有三种对象:内置对象、自定义对象、浏览器对象

在MDN上自学

9.1 Math对象——是一个对象,但不是函数对象

Math的所有属性都是静态属性

Math在内部的定义方式:

Math = {}      //Math是用 {}定义的,而不是 function Math() , 所以无法new
Math.abs = function(){}    //静态

可以new的对象是这么定义的:

function XXX(){
}
XXX.prototype.funcname = function(){}    // 实例方法
// Math 的方法/属性
Math.random(); // 返回[0,1)的小数
Math.PI
Math.E
Math.abs(null); ---0
Math.abs("abc"); ---NaN
  .ceil .floor
	.max   .min
	Math.pow(7,2);  -- 49
	Math.sqrt(16); -- 4

9.2 Date——创建实例对象使用

创建:

var birthday = new Date(1231252151251); // timestamp创建
var birthday = new Date(1995, 11, 17);   // 12月17日,月份从0开始
var birthday = new Date(1995, 11, 17, 3, 24, 0);
var d = new Date('2019-9-11')
var current = new Date();

var now = Date.now();  返回当前时间的timestamp(毫秒)

获取方法:

var now = new Date();
now.getFullYear();  // 获取年份
now.getMonth();  // 获取月份,从0开始
now.getDate();  // 获取日期
now.getDay();  // 获取星期,从0开始
now.getHours();  
now.getMinutes();
now.getSeconds();  
now.getMilliseconds() 

d.valueof()   //获得毫秒 
var d = + new Date()   //不支持H5的浏览器 通过这种方式获取毫秒

封装获取日期时间函数:

function formatDate(d) {
  //如果date不是日期对象,返回
  if (!date instanceof Date) {
    return;
  }
  var year = d.getFullYear(),
      month = d.getMonth() + 1, 
      date = d.getDate(), 
      hour = d.getHours(), 
      minute = d.getMinutes(), 
      second = d.getSeconds();
  month = month < 10 ? '0' + month : month;
  date = date < 10 ? '0' + date : date;
  hour = hour < 10 ? '0' + hour : hour;
  minute = minute < 10 ? '0' + minute:minute;
  second = second < 10 ? '0' + second:second;
  return year + '-' + month + '-' + date + ' ' + hour + ':' + minute + ':' + second;
}

9.3 String

字符串是不可变的

  • string——字符串类型——基本类型
var str = "内容";
  • String ——字符串类型——引用类型
var str2 = new String("内容"); // 引用类型
str.length
str.concat(str2,str3..)
str.indexOf('substr')
str.match(regex)
.replace  .search  .slice   .split   .substr  .substring
.toLowerCase   .toUpperCase    .trim()
String.fromcharcode()

9.4 Array

创建方式

  1. 字面值: []
  2. 构造函数: new Array()

判断是不是数组

Array.isArray()
ar instanceof Array
方法 描述
Array.isArray() 判断是不是数组
arr.length 获取长度
Array.from([1,2,3,4]) 从已有数组创建新数组
arr1.concat(arr2) 数组拼接
arr.every(callback[, thisArg]) 所有元素都要满足条件,才返回true
arr.filter(callback[, thisArg]) 返回满足条件元素构成的新数组
添加和删除方法
arr.pop() 从后面删除并且返回
arr.push(值) 在后面插入,返回数组长度
arr.shift() 删除第一个元素并且返回
.arr.unshift(值) 在前面插入,返回长度
arr.foreach(callBack) 遍历
arr.indexOf()
var str = arr.join('符号')
arr.map(callback)
arr.reverse()
arr.sort(callback)
arr.slice(1,3) 返回浅拷贝,第一个包括,第二个参数不包括

9.5 基本包装类型

隐式转换成基本包装类型

  • 普通变量没法调用属性和方法
  • 本身是基本类型,但是在执行代码的过程中,如果这种类型变量调用了属性或者方法,那么这种类型就不再是基本类型了, 而是基本包装类型; 这个变量也就变成了包装类型:

基本类型:

  • string
  • number
  • boolean
var str1 = "hello";
str1.replace("ll","HH");   // 调用了方法, 这个变量就成了基本包装类型对象

str.indexOf()
num.toString()

Boolean的基本包装类型

  • 如果是一个对象&&true, 结果为true
  • 如果是 true&&对象,返回结果为 这个对象
// boolean的基本包装类型
var flag = new Boolean(false);
flag && true  // true , 因为第一个是对象,对象是true
true && flag   // 返回是这个对象

基本包装类型 vs. 类型转换

var num2 = Number("10");  //类型转换
var num3 = new Number("10"); //基本包装类型

案例练习

交换2个变量的值:

var num1 = 10, num2 = 20;
var num1 = num1 + num2;
num2 = num1 - num2;
num1 = num1 - num2; 


var num1 = 10, num2 = 20;
var temp = num2;
num2 = num1;
num1 = temp;
console.log(num1,num2);


var num1 = 10, num2 = 20;
num1 = num1 ^ num2;
num2 = num1 ^ num2;
num1 = num1 ^ num2;

++、–练习

var a = 1;

alert( ++a + ++a + ++a);   //9
alert(a);    //4

闰年

let year = parseInt(prompt("请输入年份"));

if (year % 400 == 0){
    alert("闰年");
}
else if(year % 4 == 0 && year % 100 != 0 ){
    alert("闰年");
}
else{
    alert("不是闰年");
}

画星星、乘法口诀表

冒泡排序

var a = [4, 6, 7, 1, 3, 8, 10, 9, 5];

for (let i = 0; i < a.length - 1; i++) {

    for (let j = 0; j < a.length -i-1; j++) {

        if (a[j] > a[j + 1]) {
            let temp = a[j];
            a[j] = a[j + 1];
            a[j + 1] = temp;
        }
    }
}
alert(a);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章