01 - JavaScript 基础

计算机编程基础

编程语言 vs 标记语言

  • 编程语言:有很强的逻辑、行为能力。是主动的。如 PHP、JS、Go 等
  • 标记语言:不用于向计算机发出指令,常用于格式化和链接,其存在是用来被读取的。是被动的。如 HTML 等

计算机基础

硬件

  • 分为 输入设备、输出设备、CPU、硬盘 / 外存、内存 5大部分
    1.硬盘和内存 负责存储数据,硬盘永久存储,内存暂时存储
    2.所有程序都放在硬盘存储
    3.内存比外存速度快的原因:内存-电,硬盘-机械

初识 JavaScript

JavaScript

  • 运行在客户端的脚本语言(Script-脚本)
    1.脚本语言:不需要编译,运行过程中由 js解释器 / js引擎 逐行进行解释并执行
    2.不仅仅做前端,也可以做服务端(Node.js 服务端编程)

JS 作用

  • 表单动态校验 / 密码强度检测(JS 产生最初的目的)、网页特效、服务端开发(Node.js)、桌面程序(Electron)、App(Cordova)、控制硬件-物联网(Ruff)、游戏开发(cocos2d-js)

浏览器执行 JS 简介

  • 浏览器两部分:渲染引擎、JS 引擎
    1.渲染引擎 / 内核:用来解析 HTML、CSS,如 chrome 浏览器的 blink,老版本的 webkit
    2.JS 引擎 / JS 解释器,用来读取网页中的 JS 代码,对其处理后运行,如 chrome 浏览器的 V8(最快的 JS引擎)
  • 浏览器本身不会执行 JS 代码,而是通过内置 JS引擎 逐行执行代码

JS 组成:ECMAScript、DOM、BOM

  • ECMAScript:JS语法
    1.ECMAScript = JavaScript(网景公司) + JScript(微软公司)
    2.ECMAScript 规定了 JS 的编程语法和核心知识,是所有浏览器厂商共同遵守的一套 JS 语法工业标准
  • DOM:页面文档对象模型
    1.W3C 组织推荐的处理可扩展标记语言的标准编程接口
    2.通过 DOM 提供的接口可以对页面上的各种元素进行操作,如大小、位置、颜色等
  • BOM:浏览器对象模型
    1.提供独立于内容的,可以与浏览器窗口进行互动的对象结构
    2.通过 BOM 可以操作浏览器窗口,如弹出框、控制浏览器跳转、获取分辨率等

JS 三种书写位置:行内、内嵌、外部

1. 行内

  • 代码写在HTML标签的事件属性中(以 on 开头的属性)
  • HTML中用双引号,JS中用单引号
  • 尽量避免使用
    <!DOCTYPE html>
    <html>
    	<body>
    		<input type="button" name="" id="" value="唐伯虎" onclick="alert('秋香姐')" />
    	</body>
    </html>
    

2. 内嵌式

  • 最常用
    <!DOCTYPE html>
    <html>
    	<head>
    		<script type="text/javascript">
    			alert('沙漠骆驼');
    		</script>
    	</head>
    </html>
    

3. 外部式

  • 引用外部 JS 文件的 script 标签中间不可以写代码
    // 01.html
    <!DOCTYPE html>
    <html>
    	<head>
    		<script type="text/javascript" src="js/01.js">
    			// 此处不允许写代码
    		</script>
    	</head>
    </html>
    
    // 01.js
    alert('如果我是DJ,你还爱我吗?');
    

JS 注释

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

JS 输入输出语句

  • prompt(info);
  • alert(msg);
    浏览器弹出警示框
  • console.log(msg);
    浏览器控制台打印输出信息
    prompt('请输入您的年龄');
    alert('计算的结果是');
    console.log('我是程序员能看到的');
    
    var uNmae = prompt('请输入您的姓名');
    alert(uNmae);
    

变量

变量概念

程序在内存中申请的一块用来存放数据的空间

变量的使用

声明变量

var age;

赋值

var age = 10;

变量的初始化:声明 + 赋值

var myName = 10;

同时声明多个变量

var myName = '旗木卡卡西', address = '火影村', age = 30, email = 'kakaxi@itcast.cn', wage = 2000;

声明变量的特殊情况

  • 只声明,不赋值就使用。undefined
  • 不声明,不赋值就使用。报错
  • 不声明,只赋值就使用。允许,但会变成全局变量

变量命名规范

  • 由字母(严格区分大小写)、数字(不能以数字开头)、下划线、美元符号组成
  • 遵守驼峰命名法
  • 尽量避免用 name 作为变量名

数据类型

数据类型简介

变量的数据类型

  • JS是一种弱类型 / 动态语言,不用提前声明变量的类型。在程序运行过程中,类型由 JS引擎 根据 = 右边值的数据类型判断
  • JS拥有动态类型,即相同的变量可用作不同的类型

数据类型的分类

  • 简单数据类型(数字型 Number、字符串型 String、布尔型 Boolean、Undefined、Null)
  • 复杂数据类型(Object)

简单数据类型

数字型 Number

  • 八进制:以0开头;十六进制:以0x开头
  • 范围:
    Number.MAX_VALUE:1.7976931348623157e+308
    Number.MIN_VALUE:5e-324
  • 三个特殊值
    Infinity-InfinityNaN(Not a Number 非数值)
  • isNaN()
    用来判断一个变量是否为非数字的类型
    console.log(isNaN(21))  // false
    console.log(isNaN('a'))  // true
    

字符串型 String

  • 单引号(推荐) / 双引号【因为 HTML 标签里的属性使用的双引号,故JS中推荐使用单引号】
  • 引号嵌套:外双内单 / 外单内双
  • 转义符:\n 换行符\\ 斜杠\\' 单引号\" 双引号\t tab缩进\b 空格
  • 长度:length
    var str = 'lulu'
    alert(str.length)
    
  • 字符串拼接
    字符串 + 任何类型 = 新字符串【拼接前会把与字符串相加的任何类型转成字符串】

布尔型 Boolean

  • 布尔型 和 数字型 相加时,true的值为1,false的值为0
    console.log(true + 1);  // 2
    console.log(false + 1);  // 1
    

Undefined 和 Null

  • 一个只声明,未赋值的变量默认值为 undefined
    var variable;
    console.log(variable);  // undefined
    console.log('你好' + variable);  //你好undefined
    console.log(11 + variable);  // NaN
    console.log(true + variable);  //NaN
    
  • 一个声明变量给 null 值,里面存的值为空
    var variable = null;
    console.log(variable);  // null
    console.log('你好' + variable);  //你好null
    console.log(11 + variable);  // 11
    console.log(true + variable);  //1
    

获取变量数据类型

var num = 10;
console.log(typeof num);  // number
var str = 'lulu';
console.log(typeof str);  //string
var flag = true;
console.log(typeof flag);  //boolean
var vari;
console.log(typeof vari);  //undefined
var timer = null;
console.log(typeof timer);  // object
var age = prompt('请输入您的年龄');
console.log(typeof age);  // string

数据类型转换

什么是数据类型转换

  • 使用表单、prompt 获取的数据默认是 string 类型,若需进行加法运算,则需进行数据类型转换

常用三种方式的转换

  • 转换为 string 类型
    1.toString(),如 num.toString()
    2.String()强制转换,如 String(num)
    3.加号拼接字符串【隐式转换】,如 num + ''
  • 转换为 number 类型
    1.parseInt(string),如 parseInt('78')parseInt('120px')【js内部会自动去掉px,输出120】,parseInt('rem120px')【NaN】
    2.parseFloat(string),如 parseFloat('78.21')
    3.Number()强制转换函数,如 Number('12')
    4.js 隐式转换【即算术运算时,自动转换数据类型 】,如 '12' - 0
  • 转换为 boolean 类型
    Boolean()函数,如Boolean('')
    代表空、否定的值会被转换为 false,如'', 0, NaN, null, undefined

解释型语言和编译型语言

  • 翻译器
    程序语言翻译成机器语言的工具
  • 翻译器翻译的两种方式
    1.编译:代码执行前进行编译,生成中间代码文件
    2.解释:代码运行时及时解释,立即执行【此时翻译器又称解释器】

标识符 vs 关键字 vs 保留字

  • 标识符:开发人员为变量、属性、函数、参数取的名字。标识符不能是关键字 或 保留字
  • 关键字:JS 本身已经使用了的字。不能再用它们充当变量名 或 方法名
  • 保留字:预留的 “关键字”,未来可能成为关键字,不能使用它们当变量名 或 方法名

JS 运算符

算术运算符

  • 浮点数值的最高精度是 17 位小数,但在进行算数运算时其精确度远远不如整数。所以不要直接判断两个浮点数是否相等
  • 开发中,大多使用后置递增 / 减

比较运算符

  • == != 不要求数据类型一致,该运算符会隐式转型
  • === !== 要求数据类型一致

逻辑运算符

短路运算(逻辑中断)

  • 原理
    有多个表达式(值)时,左边表达式(值)可以确定结果时,就不再继续运算右边的表达式的值
  • 逻辑与 表达式1 && 表达式2
    1.若 表达式1 为真,则返回 表达式2
    2.若 表达式1 为假,则返回 表达式1
  • 逻辑或 表达式1 || 表达式2
    1.若 表达式1 为真,则返回 表达式1
    2.若 表达式1 为假,则返回 表达式2
    console.log(123 || 456);  // 123
    console.log(123 || 456 || 789);  // 123
    console.log(0 || 456 || 456 + 123);  // 456
    

运算符优先级

  • 优先级
    1.小括号 ()
    2.一元运算符 ++ -- !【!优先级很高】)
    3.算术运算符 先 * / % 后 + -
    4.关系运算符 > >= < <=
    5.相等运算符 == != === !==
    6.逻辑运算符 先 && 后 ||
    7.赋值运算符 =
    8.逗号运算符 ,

JS 流程控制

switch 语句

  • switch(num) 中 num 的值 和 case 里的值相匹配时为全等 ===
  • switch 语句 vs if 语句
    1.switch语句 比 if语句 效率更高
    2.分支较少时,if语句 执行效率高于 switch语句
    3.分支较多时,switch语句 执行效率高于 if语句

示例

// 1. 打印一行五列*
var str1 = '';
for (var i = 1; i <= 5; i++) {
	str1 += '*';  // 若直接在此 console.log('*'),则 * 打印出来为一列,即会换行
}
console.log(str1);

// 2. 打印五行五列*
var str2 = '';
for (var i = 1; i <= 5; i++) {
	for (var j = 1; j <= 5; j++) {
		str2 += '*';
	}
	str2 += '\n';
}
console.log(str2);

断点调试

  • Chrome浏览器中,F12 --> Source --> 找到需要调试的文件 --> 设置断点
  • Watch:可监视变量值的变化
  • F11:程序单步执行

标识符命名规则

  • 变量名用名词,函数名用动词
  • 操作符的左右两侧各保留一个空格
    for (var i = 1; i <= 5; i++) {
    	if (i == 3) {
    		break;  // 单行注释前面注意有个空格
    	}
    	console.log('我正在吃第' + i + '个包子呢');
    }
    if (true) {
    }
    

数组

创建数组的方式

1. 利用 new 关键字

  • var 数组名 = new Array();

2. 利用数组字面量【使用最多】

  • var 数组名 = [];
    var 数组名 = ['lulu', 12, true]; 【可存放任意类型的数据】

获取数组元素 - 数组索引

  • 数组名[索引]
  • arr.length 动态监测数组元素的个数
  • console.log(sum, average); 输出多个变量,可用逗号分隔

数组中新增元素

1. 修改 length

  • 数组的 length 属性可读写
  • 示例
    var arr = ['red', 'green', 'blue', 'pink'];
    arr.length = 7;
    console.log(arr);  // "red,green,blue,pink,,,"
    console.log(arr[4]);  // undefined
    

2. 修改数组索引【常用】

  • 示例
    var arr = ['red', 'green', 'blue', 'pink'];
    arr[4] = 'hotpink';
    console.log(arr);  // "red,green,blue,pink,hotpink"
    

数组案例

追加多个元素给新数组

var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
var newArr = [];
for (var i = 0; i < arr.length; i++) {
	if (arr[i] >= 10) {
		newArr[newArr.length] = arr[i];  // 重点
	}
}
console.log(newArr);

冒泡排序

var arr = [4, 1, 2, 3, 5];
for (var i = 0; i <= arr.length - 1; i++) {  // 循环趟数
	for (var j = 0; j <= arr.length - i - 1; j++) {  //比较次数
		if (arr[j] > arr[j + 1]) {
			var temp = arr[j];
			arr[j] = arr[j + 1];
			arr[j + 1] = temp;
		}
	}
}
console.log(arr);

函数

函数的使用

1. 声明

function 函数名() {}

2. 调用

函数名();

函数的参数

两种参数

  • 形参:函数定义时传递的参数,当前不知道是什么
  • 实参:函数调用时传递的参数,实参是传递给形参的

函数形参和实参个数不匹配的问题

  • 实参个数 == 形参个数:输出正确结果
  • 实参个数 > 形参个数:只取到形参的个数
  • 实参个数 < 形参个数:多的形参定义为 undefined,结果为 NaN【JS 中,形参默认值为 undefined】

函数的返回值

  • return 之后的代码不被执行
  • return 只能返回一个值,若用逗号隔开多个值,以最后一个为准
    function fn(num1, num2) {
    		return num1, num2;
    	}
    	console.log(fn(1, 2));  // 2
    
  • 若想函数 return 多个值,则考虑 return 一个数组
    function getResult(num1, num2) {
    	return [num1 + num2, num1 - num2, num1 * num2, num1 / num2];
    }
    console.log(getResult(1, 2));  // 3,-1,2,0.5
    
  • 若函数有 return,则返回 return 后面的值;若函数无 return,则返回 undefined
  • 示例【数组做形参】
    function getArrMax(arr) {
    	var max = arr[0];
    	for (var i = 1; i <= arr.length; i++) {
    		if (arr[i] > max) {
    			max = arr[i];
    		}
    	}
    	return max;
    }
    var re = getArrMax([5, 2, 99, 101, 67, 77]);
    console.log(re);
    

arguments 的使用

  • 不确定有多少个参数需要传递时,可用 arguments 获取
  • arguments 是当前函数的一个内置对象,所有函数【只有函数】都内置了一个 arguments 对象,arguments 对象中存储了传递的所有实参
  • arguments 是一个伪数组,有 length 属性;按索引方式存储数据;不具有数组的 push、pop 等方法
  • 示例
    function fn() {
    	console.log(arguments);
    	console.log(arguments.length);
    	console.log(arguments[2]);
    	for (var i = 0; i < arguments.length; i++) {
    		console.log(arguments[i]);
    	}
    }
    fn(1, 2, 3);
    fn(1, 2, 3, 4, 5);
    

函数的两种声明方式

1. 命名函数(函数关键字)

function fn() {
}
fn();

2. 匿名函数(函数表达式)

  • fun 是变量名,非函数名
  • 函数表达式中存的是函数
    var fun = function() {
    }
    fun();
    

作用域

作用域

  • es6之前,分为 全局作用域、局部作用域(又名函数作用域)
  • es6及es6之后,新增 块级作用域{}
    if (3 < 5) {
    	var num = 10;
    }
    console.log(num);  // 外面的不能调用 num
    

变量的作用域

变量

  • 全局变量
    特殊情况:在函数内部未声明直接赋值的变量也是全局变量(不建议使用)
  • 局部变量
    函数的形参实际上是局部变量

全局变量 vs 局部变量

  • 全局变量:浏览器关闭时才会被销毁,故较占内存
  • 局部变量:其所在代码块被执行时,会被初始化,代码块运行结束后,被销毁,故更节省内存

作用域链

  • js 引擎运行 js 分为两步:预解析 + 代码执行

预解析

  • js 引擎会把 js 中所有的 var 和 function 提升到当前作用域的最前面

变量预解析和函数预解析

  • 预解析分为:变量预解析(变量提升) + 函数预解析(函数提升)
  • 变量提升:把所有的变量声明提升到当前作用域最前面,不提升赋值操作
  • 函数提升:把所有的函数声明提升到当前作用域最前面,不调用函数
  • 注:函数表达式(匿名函数)中,调用必须写在函数表达式下面,详见 预解析案例4问

预解析案例

// 1问
console.log(num);  // 报错

// 2问
console.log(num);  // undefined
var num = 10;
/*
 相当于执行了以下代码
 var num;
 console.log(num);
 num = 10;
*/

// 3问
fn();
function fn() {
	console.log(11);  // 11
}

// 4问
fun();
var fun = function() {
	console.log(22);  // 报错
}
/*
 相当于执行了以下代码
 var fun;  // fun 是变量,非函数
 fun();
 fun = function() {
	console.log(22);
 }
*/
f1();
console.log(c);  // 9
console.log(b);  // 9
console.log(a);  // 报错
function f1() {
	var a = b = c = 9;
	console.log(a);  // 9
	console.log(b);  // 9
	console.log(c);  // 9
}
/*
  相当于以下代码
  function f1() {
	var a;
	a = b = c = 9;  // b, c 未声明直接赋值,当全局变量看
					// 集体声明 var a = 9, b = 9, c = 9;
	console.log(a);  // 9
	console.log(b);  // 9
	console.log(c);  // 9
  }
  f1();
  console.log(c);  // 9
  console.log(b);  // 9
  console.log(a);  // 报错
 */

对象

  • JS 中,对象是一组无序的相关属性方法的集合

创建对象的三种方式

1. 字面量【逗号分隔】

var obj = {
	uname: '张三丰',
	age: 18,
	sex: '男',
	sayHi: function() {  // 匿名函数
		console.log('hi!');
	}
}
console.log(obj.uname);
console.log(obj['age']);
obj.sayHi();

2. new Object【分号分隔】

var obj = new Object();
obj.uname = '张三丰';
obj.age = 18;
obj.sex = '男';
obj.sayHi = function() {
	console.log('Hi!');
}
console.log(obj.uname);
console.log(obj['sex']);
obj.sayHi();

3. 构造函数

  • 构造函数是特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值
  • 总与 new 运算符一起使用
  • 构造函数泛指一大类,对象实例特指一个事务
    对象的实例化:利用构造函数创建对象的过程
  • 示例
    function Star(uname, age, sex) {
    	this.name = uname;
    	this.age = age;
    	this.sex = sex;
    	this.sing = function(song) {
    		console.log(song);
    	}
    }
    var lh = new Star('鹿晗', 33, '男');
    console.log(typeof lh);  // object
    console.log(lh.name);  // 鹿晗
    console.log(lh['sex']);  // 男
    lh.sing('夏令时');  // 夏令时
    
    注:
    1. 构造函数名字首字母需大写
    2. 构造函数不需要 return 即可返回结果
    3. 调用构造函数,必须使用 new
    4. 属性、方法前必须加 this

new 关键字

  • new 关键字执行过程
    1.new 构造函数在内存中创建一个空对象
    2.this 指向新创建的空对象
    3.执行构造函数里的代码,给这个空对象添加属性和方法
    4.返回这个对象(构造函数不需要 return,即可返回结果)

遍历对象属性

var obj = {
	name: '鹿晗',
	age: 33,
	sex: '男',
	fn: function() {}
}
for (var k in obj) {  // for...in 中常用变量 k 或 key
	console.log(k);  // k变量输出得到的是 属性名
	console.log(obj[k]);  // obj[k]得到的是 属性值
}

内置对象

内置对象

  • JS 的三种对象:自定义对象【属于ECMAScript】、内置对象【属于ECMAScript】、浏览器对象【JS 独有】
  • 内置对象:JS 语言自带的供开发者使用的一些对象,并提供了一些常用的 / 基本而必要的功能
  • JS 常用内置对象:Math、Date、Array、String

查文档

两种常用方式

  • MDN(Mozilla 开发者网络):提供了有关开放网络技术(Open Web)的信息,包括 HTML、CSS、万维网、HTML5 应用的 API。https://developer.mozilla.org/zh-CN/
  • W3C

如何学习对象中的方法

  • 查阅该方法的功能
  • 查看里面参数的意义和类型
  • 查看返回值的意义和类型
  • 通过 demo 进行测试

Math 对象

  • Math 对象不是构造函数,故不需要 new 来调用,而是直接使用其属性和方法
  • Math.PI // 圆周率
    console.log(Math.max(1, 99, 'lulu'));  // NaN
    console.log(Math.max());  // -Infinity
    
    // 利用对象封装自己的数学对象,里面有 PI 最大值 最小值
    var myMath = {
    	PI: 3.141592653,
    	max: function() {
    		var max = arguments[0];
    		for (var i = 1; i < arguments.length; i++) {
    			if (arguments[i] > max) {
    				max = arguments[i];
    			}
    		}
    		return max;
    	},
    	min: function() {
    		var min = arguments[0];
    		for (var i = 1; i < arguments.length; i++) {
    			if (arguments[i] < min) {
    				min = arguments[i];
    			}
    		}
    		return min;
    	}
    }
    console.log(myMath.PI);
    console.log(myMath.max(1, 5, 9));
    console.log(myMath.min(1, 5, 9));
    
  • Math.floor() //向下取整
  • Math.ceil() // 向上取整
  • Math.round() // 四舍五入版【就近取整】【.5特殊,往大了取】
    console.log(Math.round(1.1));  // 1
    console.log(Math.round(1.5));  // 2
    console.log(Math.round(1.9));  // 2
    console.log(Math.round(-1.1));  // -1
    console.log(Math.round(-1.5));  // -1【
    
  • Math.abs() // 绝对值
    console.log(Math.abs('-1'));  // 1【隐式转换】
    console.log(Math.abs('pink'));  // NaN
    
  • Math.max() / Math.min() //求最大 / 小值
  • Math.random() // 随机数【返回一个随即小数,[0, 1)】【该方法无形参】
    console.log(Math.random());
    
    // 得到两数之间的随机整数,且包含这两个整数
    function getRandom(min, max) {
    	return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    console.log(getRandom(1, 10));
    
    // 随机点名
    var arr = ['鹿晗', 'lulu', '上海', '武汉'];
    console.log(arr[getRandom(0, arr.length - 1)]);
    

日期对象

  • Date 对象是一个构造函数,故需实例化后才能使用,即必须 new
  • 时间戳:Date 对象是基于 1970年1月1日(世界标准时间)起的毫秒数
  • var date = new Date()【返回系统的当前时间】
    var date = new Date(2019, 10, 1) // Fri Nov 01 2019 00:00:00 GMT+0800 (中国标准时间)【返回月份的比输入的大1】
    var date = new Date('2019-10-1 7:7:7') // Tue Oct 01 2019 07:07:07 GMT+0800 (中国标准时间)
    var date = new Date('2019/10/1 7:7:7') // Tue Oct 01 2019 07:07:07 GMT+0800 (中国标准时间)
  • getFullYear() // 获取当年
  • getMonth() // 获取当月【0-11】
  • getDate() // 获取当天日期
  • getDay() // 获取星期几【周日0 周六6】
  • getHours() // 获取当前小时
  • getMinutes() // 获取当前分钟
  • getSeconds() // 获取当前秒钟
  • valueOf() // 获取时间戳
    getTime() // 获取时间戳
    +new Date() // 获取时间戳【常用】
    Date.now() // 获取时间戳【H5 新增,有兼容性问题】
    var date = new Date();
    console.log(date.valueOf());
    console.log(date.getTime());
    
    var now = + new Date();
    console.log(now);
    
    var now1 = Date.now();
    console.log(now1);
    
  • 示例
    var date = new Date();
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    var dates = date.getDate();
    var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
    var day = date.getDay();
    console.log('今天是:' + year + '年' + month + '月' + dates + '日' + arr[day]);  // 今天是:2023年8月29日星期二
    
    // 倒计时
    // d = parseInt(总秒数/ 60/60 /24); // 计算天数
    // h = parseInt(总秒数/ 60/60 %24) // 计算小时
    // m = parseInt(总秒数 /60 %60 ); // 计算分数
    // s = parseInt(总秒数%60); // 计算当前秒
    function countDown(time) {
    	var nowTime = +new Date();
    	var inputTime = +new Date(time);
        var times = (inputTime - nowTime) / 1000; //总秒数 
        var d = parseInt(times / 60 / 60 / 24);
        d = d < 10 ? '0' + d : d;
        var h = parseInt(times / 60 / 60 % 24);
        h = h < 10 ? '0' + h : h;
        var m = parseInt(times / 60 % 60);
        m = m < 10 ? '0' + m : m;
        var s = parseInt(times % 60);
        s = s < 10 ? '0' + s : s;
        return d + '天' + h + '时' + m + '分' + s + '秒';
    }
    console.log(countDown('2023-9-1 00:00:00'));
    

数组对象

创建数组的两种方式

  • 利用数组字面量
    var arr = [1, 2, 3]
  • 利用 new Array()
    var arr1 = new Array(2) // 数组长度为2,即该数组中有2个空元素
    var arr2 = new Array(2, 3) // 数组长度为2,该数组中有两元素2和3

检测是否为数组

  • 利用 instanceof 运算符
    arr instanceof Array
  • 利用 isArray() 方法【 H5 新增,ie9 以上版本支持】【优】
    Array.isArray(arr)
  • 示例
    function reverse(arr) {
    	if (arr instanceof Array) {
    		var newArr = [];
    		for (var i = arr.length - 1; i >= 0; i--) {
    			newArr[newArr.length] = arr[i];
    		}
    		return newArr;
    	} else {
    		return 'error 这个参数要求必须是数组格式 [1,2,3]'
    	}
    }
    console.log(reverse([1, 2, 3]));
    console.log(reverse(1, 2, 3));
    

添加删除数组元素的方法

  • push(para1...)【末尾添加一/多个元素,修改了原数组】【返回新的长度】
  • pop()【删除数组最后一个元素,修改了原数组】【返回它删除的元素的值】
  • unshift(para1...)【开头添加一/多个元素,修改了原数组】【返回新的长度】
  • shift()【删除数组第一个元素,修改了原数组】【返回它删除的元素的值】
  • 示例
    var arr = [1, 2, 3];
    console.log(arr.push('lu'));  // 4
    console.log(arr);  // 1,2,3,lu
    
    console.log(arr.unshift('鹿'));  // 5
    console.log(arr);  // 鹿,1,2,3,lu
    
    console.log(arr.pop());  // lu
    console.log(arr);  // 鹿,1,2,3
    
    console.log(arr.shift());  // 鹿
    console.log(arr);  // 1,2,3
    

数组排序

  • reverse()【颠倒数组中元素的顺序,会改变原来的数组】【返回新数组】
    var arr = ['a', 'b', 'c'];
    arr.reverse();
    console.log(arr);  // c,b,a
    
  • sort()【对数组的元素进行排序,会改变原来的数组】【返回新数组】
    var arr = [13, 4, 77, 1, 7];
    arr.sort();
    console.log(arr);  // 1,13,4,7,77
    
    arr.sort(function(a, b) {
    	return a - b;
    })
    console.log(arr);  // 1,4,7,13,77【升序】
    
    arr.sort(function(a, b) {
    	return b - a;
    })
    console.log(arr);  // 77,13,7,4,1【降序】
    

数组索引方法

  • indexOf()【若存在,返回出现的第一个索引;否则,返回 -1】
  • lastIndexOf()【若存在,返回出现的最后一个索引;否则,返回 -1】
  • 示例
    function unique(arr) {
    	var newArr = [];
    	for (var i = 0; i < arr.length; i++) {
    		if (newArr.indexOf(arr[i]) === -1) {
    			newArr.push(arr[i]);
    		}
    	}
    	return newArr;
    }
    var demo = unique(['a', 'b', 'a', 'c', 'a', 'd']);
    console.log(demo);  // a,b,c,d
    

数组转换为字符串

  • toString()【把数组转换成字符串,逗号分隔每一项】【返回一个字符串】
    var arr = [1, 2, 3];
    console.log(arr.toString());  // 1,2,3
    
  • join('分隔符')【把数组中的所有元素转换成一个字符串】【返回一个字符串】
    var arr = ['g', 'b', 'p'];
    console.log(arr.join());  // g,b,p
    console.log(arr.join('-'));  // g-b-p
    console.log(arr.join('&'));  // g&b&p
    

其余常用数组操作

  • concat()【连接两/多个数组,不改变原数组】【返回一个新数组】
  • slice()【数组截取 slice(begin, end)】【返回被截取项目的新数组】
  • splice()【数组删除 splice(第几个开始, 要删除个数),改变原数组】【返回被删除项目的新数组】【重点】
    注:slice() 和 splice() 目的基本相同,splice() 是重点

字符串对象

  • 字符串所有方法,都不会修改字符串本身(字符串不可变性),操作完成后会返回一个新的字符串

基本包装类型

  • JS 中三个特殊的引用类型:String、Number、Boolean
  • 基本包装类型:把简单数据类型包装成复杂数据类型,这样基本数据类型就有了属性和方法
  • 详解
    var str = 'andy';
    console.log(str.length);
    // 基本数据类型是没有属性和方法的,对象才有属性和方法
    // 上述代码可以执行的原因:js会把基本数据类型包装成复杂数据类型
    
    // 其等价代码如下
    var temp = new String('andy');  // 生成临时变量,把简单类型包装为复杂数据类型
    str = temp;
    temp = null;  // 销毁临时变量
    

字符串的不可变

  • 字符串被重新赋值时,值不变,仍在内存中。看上去内容有变化,是因为在内存中新开辟了一个内存空间。故大量拼接字符串的时候会有效率问题,应尽量避免
  • 示例
    var str = '';
    for (var i = 0; i < 100000; i++) {
    	str += i;  // 效率问题,应避免使用
    }
    console.log(str);
    

根据字符返回位置

  • indexOf('要查的字符', 开始的位置)【若不存在,则返回 -1】【只返回一个】
    var str = '改革春风吹满地,春天来了';
    console.log(str.indexOf('春'));  // 2
    console.log(str.indexOf('春', 3));  // 8
    
  • lastIndexOf()【只返回一个】
  • 示例
    // 查找字符串"abcoefoxyozzopp"中所有o出现的位置以及次数
    var str = 'abcoefoxyozzopp';
    var sum = 0;
    var index = str.indexOf('o');
    while (index !== -1) {
    	console.log(index);
    	index = str.indexOf('o', index + 1);  // 重点
    	sum++;
    }
    console.log('o出现的次数是:' + sum);
    

根据位置返回字符

  • charAt(index)【返回指定位置的字符】
    var str = 'andy';
    for (var i = 0; i < str.length; i++) {
    	console.log(str.charAt(i));  // a n d y
    }
    
  • charCodeAt(index)【返回指定位置字符的ASCII码】
    var str = 'andy';
    for (var i = 0; i < str.length; i++) {
    	console.log(str.charCodeAt(i));  // 97 110 100 121
    }
    
  • str[index]【返回指定位置的字符】【HTML5,IE8+ 支持】
    var str = 'andy';
    for (var i = 0; i < str.length; i++) {
    	console.log(str[i]);  // a n d y
    }
    
  • 示例
    // 判断一个字符串中出现次数最多的字符,并统计其次数
    var str = 'abcoefoxyozzopp';
    var obj = {};
    for (var i = 0; i < str.length; i++) {
    	var chars = str.charAt(i);
    	if (obj[chars]) {
    		obj[chars]++;
    	} else {
    		obj[chars] = 1;
    	}
    }
    var max = 0;
    var ch = '';
    for (var k in obj) {  // 遍历对象只能用 for...in 语句,k 得到的是属性名
    	if (obj[k] > max) {  // obj[k] 得到的是属性值
    		max = obj[k];
    		ch = k;
    	}
    }
    console.log('出现次数最多的字符是' + ch + ',共出现了' + max + '次');  // 出现次数最多的字符是o,共出现了4次
    

字符串操作方法

  • concat(str1, str2, str3...)【用于连接两/多个字符串】【等效于+(常用)】
    var str = 'lu';
    console.log(str.concat('lu'));  // lulu
    
  • substr(start[, length])【若省略第二个参数 length,则返回的字符串是从起始位置到尾的】
    var str = 'abcdef';
    console.log(str.substr(2, 3));  // cde
    
  • slice(start, end)【取不到 end】
  • substring(start, end)【取不到 end】【基本和 slice 相同,但不接受负值】
  • replace(被替换的字符串, 要替换的字符串)【只替换第一个字符】
    var str = 'abcoefoxyozzopp';
    while (str.indexOf('o') !== -1) {
    	str = str.replace('o', '*');
    }
    console.log(str);  // abc*ef*xy*zz*pp
    
  • split()【可将字符串切分为数组】【返回的是新数组】
    var str = 'a,b,c,d';
    console.log(typeof str.split(','));  // Object
    console.log(str.split(','));  // a,b,c,d 数组
    
  • toUpperCase()
    toLowerCase()

简单类型与复杂类型

简单类型与复杂类型

简单类型 / 基本类型 / 值类型

  • 存储时变量中存储的是值本身,如 string、number、boolean、undefined、null
  • 值类型变量的数据直接存放在变量(栈空间)中

复杂类型 / 引用类型

  • 存储时变量中存储的仅仅是地址(引用),如 Object、Array、Date(系统对象、自定义对象)(通过 new 关键字创建的对象)
  • 引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中
  • 简单数据类型 null 返回的是一个空对象 object
    // 如果有个变量我们打算以后存储为对象,暂时没想好放啥,这时可赋为 null
    var timer = null;
    console.log(typeof timer);  // object
    

堆和栈

  • js 中没有堆栈的概念,但底层用堆栈概念

栈【位于内存】

  • 由 OS 自动分配、释放存放函数的参数值、局部变量的值等
  • 简单数据类型存放到栈中

堆【位于内存】

  • 由程序员分配、释放复杂类型,若程序员不释放,由垃圾回收机制回收
  • 复杂数据类型存放到堆中

简单类型传参

  • 函数的形参可看做一个变量,当我们把值类型变量传给形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量
  • 示例
    function fn(a) {
    	a++;
    		console.log('a: ' + a);   // a: 11
    }
    var x = 10;
    fn(x);
    console.log('x: ' + x);  // x: 10
    

复杂类型传参

  • 函数的形参可看做一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象
  • 示例
    function Person(name) {
    	this.name = name;
    }
    function f1(x) {  // x = p
    	console.log('2: ' + x.name);  // 2: 刘德华
    	x.name = "张学友";
    	console.log('3: ' + x.name);  // 3: 张学友
    }
    var p = new Person("刘德华");
    console.log('1: ' + p.name);  // 1: 刘德华
    f1(p);
    console.log('4: ' + p.name);  // 4: 张学友
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值