计算机编程基础
编程语言 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
、-Infinity
、NaN(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 为假,则返回 表达式2console.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('夏令时'); // 夏令时
- 构造函数名字首字母需大写
- 构造函数不需要 return 即可返回结果
- 调用构造函数,必须使用 new
- 属性、方法前必须加 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: 张学友