数据类型
简单数据类型
- number:数值型.既可以保存整数,也可以保存小数
* Infinity :代表无穷大,大于任何数值
* -Infinity:代表无穷小,小于任何数值.
* Nan:not a number ,代表一个非数值.isNan,用来判断一个变量是否为非数值类型,返回true 或false. isNan(变量名) - string:字符串.
* 转义符:
\n 换行符,n 是 newline 的意思
\ \ 斜杠 \
\' ' 单引号
\" ”双引号
\t tab 缩进
\b 空格 ,b 是 blank 的意思
* length:通过字符串的 length 属性可以获取整个字符串的长度
* +:多个字符串之间可以使用 + 进行拼接 + 号总结口诀:数值相加 ,字符相连
- Boolean:布尔值类型,true或false 布尔型和数字型相加的时候, true 的值为 1 ,false 的值为 0
- undefined: var a;声明了变量a但是没有赋值,此时a = undefined.
var variable;
console.log(variable); // undefined
console.log('你好' + variable); // 你好undefined
console.log(11 + variable); // NaN
console.log(true + variable); // NaN
- null: 空值.
var vari = null;
console.log('你好' + vari); // 你好null
console.log(11 + vari); // 11
console.log(true + vari); // 1
获取变量数据类型 typeof
数据类型转换
转换为字符串
三种转换方式,更多第三种加号拼接字符串转换方式, 这一种方式也称之为隐式转换
转换为数字型
隐式转换是我们在进行算数运算的时候,JS 自动转换了数据类型
转换为布尔型
‘’、0、NaN、null、undefined会被转换为 false,其余值都会被转换为 true
解释型语言— Javascript是一种解释型语言,解释器是在代码运行时按照从上到下的顺序逐行解释并执行。
运算符
算数运算符
运算符 描述
+ 加
- 减
* 乘
/ 除
% 取余
++ 递增+1 ++num:先自增,然后再返回值。num++:先返回值然后再自增
-- 递减-1 --num:先自减,然后再返回值。num--:先返回值然后再自减
比较运算符
逻辑运算符
- 逻辑与&&:必须两边的表达式都是true才返回true,否则返回false
- 逻辑或 ||:必须两边的表达式都是false,才返回false。只要有一边的表达式是true就返回true
- 逻辑非 !:取反,!true返回false,!false返回true
- 短路运算:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值。例如:
//如果第一个表达式的值为真,则返回表达式2
//如果第一个表达式的值为假,则返回表达式1
console.log( 123 && 456 ); // 456
console.log( 0 && 456 ); // 0
console.log( 123 && 456&& 789 ); // 789
//如果第一个表达式的值为真,则返回表达式1
//如果第一个表达式的值为假,则返回表达式2
console.log( 123 || 456 ); // 123
console.log( 0 || 456 ); // 456
console.log( 123 || 456 || 789 ); // 123
运算符优先级
流程控制语句
if语句
if else 语句
if else if 语句
三元表达式
- 语法结构
表达式1 ? 表达式2 : 表达式3;
var result 10 > 0 ? '是' : '否'
console.log(result); //'是'
- 执行思路
- 如果表达式1为 true ,则返回表达式2的值,如果表达式1为 false,则返回表达式3的值
switch语句
switch( 表达式 ){
case value1:
// 表达式 等于 value1 时要执行的代码
break;
case value2:
// 表达式 等于 value2 时要执行的代码
break;
default:
// 表达式 不等于任何一个 value 时要执行的代码
}
注意:执行case 里面的语句时,在最后一定要加break,如果没有break,则会继续执行下一个case里面的语句。如果没有一个case的表达式匹配switch中的表达式则会执行default的语句。
循环
for循环
for(初始化变量; 条件表达式; 操作表达式 ){
//循环体语句
}
//输出10此hello
for(var i = 0; i < 10; i++){
consolo.log("hello");
}
- 执行过程:
- 初始化变量,初始化操作在整个 for 循环只会执行一次。
- 执行条件表达式,如果为true,则执行循环体语句,否则退出循环,循环结束。
- 执行操作表达式,此时第一轮结束。
- 第二轮开始,直接去执行条件表达式(不再初始化变量),如果为 true ,则去执行循环体语句,否则退出循环。
- 继续执行操作表达式,第二轮结束。
- 后续跟第二轮一致,直至条件表达式为假,结束整个 for 循环。
双重for循环
for (外循环的初始; 外循环的条件; 外循环的操作表达式) {
for (内循环的初始; 内循环的条件; 内循环的操作表达式) {
需执行的代码;
}
}
- 内层循环可以看做外层循环的循环体语句
- 内层循环执行的顺序也要遵循 for 循环的执行顺序
- 外层循环执行一次,内层循环要执行全部次数
while循环
while (条件表达式) {
// 循环体代码
}
执行思路:
- 1 先执行条件表达式,如果结果为 true,则执行循环体代码;如果为 false,则退出循环,执行后面代码
- 2 执行循环体代码
- 3 循环体代码执行完毕后,程序会继续判断执行条件表达式,如条件仍为true,则会继续执行循环体,直到循环条件为 false 时,整个循环过程才会结束
注意:使用 while 循环时一定要注意,它必须要有退出条件,否则会成为死循环
do-while循环
do {
// 循环体代码 - 条件表达式为 true 时重复执行循环体代码
} while(条件表达式);
执行思路
- 1 先执行一次循环体代码
- 2 再执行条件表达式,如果结果为 true,则继续执行循环体代码,如果为 false,则退出循环,继续执行后面代码
注意:先再执行循环体,再判断,do…while循环语句至少会执行一次循环体代码
continue、break
continue关键字:跳出本次循环继续下一次循环(本次循环中continue后面的代码会少执行一次)。
break关键字:直接跳出整个循环(循环结束)。
数组
数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。
创建数组
//利用new 构造函数
var 数组名 = new Array();
var arr = new Array(); //创建一个空数组
注意:上面代码中arr创建出的是一个空数组,如果需要使用构造函数Array创建非空数组,可以在创建数组时传入参数
参数传递规则如下:
- 如果只传入一个参数,则参数规定了数组的长度
- 如果传入了多个参数,则参数称为数组的元素
//利用数组字面量创建数组
var 数组名 = [];
var arr = ['白','黑','红','蓝'];
数组中可以存放任意类型的数据,例如字符串,数字,布尔值等.
var arr = [1,'白',true,20.11];
获取数组中的元素
索引 (下标) :用来访问数组元素的序号(数组下标从 0 开始)
// 定义数组
var arrStus = [1,2,3];
// 获取数组中的第2个元素
alert(arrStus[1]);
注意:如果访问时数组没有和索引值对应的元素,则得到的值是undefined
遍历数组
var arr = ['red','green', 'blue'];
for(var i = 0; i < arr.length; i++){
console.log(arrStus[i]);
}
length:数组的长度 — 使用数组名.length可以获取到数组元素的数量
- 注意:
- 此处数组的长度是数组元素的个数 ,不要和数组的索引号混淆。
- 当我们数组里面的元素个数发生了变化,这个 length 属性跟着一起变化
- 数组的length属性可以被修改:
- 如果设置的length属性值大于数组的元素个数,则会在数组末尾出现空白元素;
- 如果设置的length属性值小于数组的元素个数,则会把超过该值的数组元素删除
数组中新增元素
数组[ 数组.length ] = 新数据;
函数
函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。
声明函数
// 声明函数
function 函数名() {
//函数体代码
}
- function 是声明函数的关键字,必须小写
- 由于函数一般是为了实现某个功能才定义的, 所以通常我们将函数名命名为动词,比如 getSum
调用普通函数
// 调用函数
函数名(); // 通过调用函数名来执行函数体代码
/*
计算1-100之间值的函数
*/
// 声明函数
function getSum(){
var sumNum = 0;// 准备一个变量,保存数字和
for (var i = 1; i <= 100; i++) {
sumNum += i;// 把每个数值 都累加 到变量中
}
alert(sumNum);
}
// 调用函数
getSum();
注意:声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码。
函数的参数
参数的作用 : 在函数内部某些值不能固定,我们可以通过参数在调用函数时传递不同的值进去。
// 带参数的函数声明
function 函数名(形参1, 形参2 , 形参3...) { // 可以定义任意多的参数,用逗号分隔
// 函数体
}
// 带参数的函数调用
函数名(实参1, 实参2, 实参3...);
- 调用的时候实参值是传递给形参的
- 实参和形参的多个参数之间用逗号(,)分隔
函数形参和实参数量不匹配时
注意:在JavaScript中,形参的默认值是undefined。形参的个数可以和实参个数不匹配,但是结果不可预计,我们尽量要匹配
函数的返回值
return 语句
返回值:函数调用整体代表的数据;函数执行完成后可以通过return语句将指定数据返回 。
// 声明函数
function 函数名(){
...
return 需要返回的值;
}
// 调用函数
函数名(); // 此时调用函数就可以得到函数体内return 后面的值
- 在使用 return 语句时,函数会停止执行,并返回指定的值
- 如果函数没有 return ,返回的值是 undefined
break ,continue ,return 的区别
- break :结束当前的循环体(如 for、while)
- continue :跳出本次循环,继续执行下次循环(如 for、while)
- return :不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码
arguments的使用
当不确定有多少个参数传递的时候,可以用 arguments 来获取。JavaScript 中,arguments实际上它是当前函数的一个内置对象。所有函数都内置了一个 arguments 对象,arguments 对象中存储了传递的所有实参。arguments展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点:
- 具有 length 属性
- 按索引方式储存数据
- 不具有数组的 push , pop 等方法
注意:在函数内部使用该对象,用此对象获取函数调用时传的实参。
函数的声明方式
- 自定义函数方式(命名函数)
利用函数关键字 function 自定义函数方式
// 声明定义方式
function fn() {...}
// 调用
fn();
- 因为有名字,所以也被称为命名函数
- 调用函数的代码既可以放到声明函数的前面,也可以放在声明函数的后面---(因为javascript中会把函数的声明提升到当前作用域的前面,所以即使放在声明函数的前面也不会报错)
- 函数表达式方式(匿名函数)
利用函数表达式方式的写法如下:
// 这是函数表达式写法,匿名函数后面跟分号结束
var fn = function(){...};
// 调用的方式,函数调用必须写到函数体下面
fn();
- 因为函数没有名字,所以也被称为匿名函数
- 这个fn 里面存储的是一个函数
- 函数表达式方式原理跟声明变量方式是一致的
- 函数调用的代码必须写到函数体后面
new Function实例对象
Function 里面参数都必须是字符串格式 第三种方式执行效率低,也不方便书写,因此较少使用 所有函数都是 Function 的实例(对象) 函数也属于对象
var fn = new Function('a', 'b', 'console.log( a + b)');
fn(1, 2);
函数的调用方式
//1.普通函数
function fn() {
console.log('普通函数');
}
fn();
//2.对象的方法
var obj = {
say: function () {
console.log('对象中的方法');
}
}
obj.say();
//3.构造函数
function Star() { }
new Star();
//4.绑定事件函数
btn.onclick = function () { } //点击绑定的按钮就可以调用函数
//5.定时器函数
setTimeout(function () {
console.log('定时器函数');
}, 1000);//这个函数由定时器1秒后调用
//立即执行函数(自调用函数)
(function () {
console.log('自调用函数');
})()
作用域
* 全局作用域---作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件。
* 局部作用域---作用于函数内部的代码环境,就是局部作用域.
* 全局变量---在全局作用域声明的变量.
-全局变量在代码的任何位置都可以使用
-特殊情况下,在函数内声明变量时省略var关键字,这个变量也是全部变量(不建议使用)
* 局部变量---在局部作用域声明的变量.
-局部变量只能在函数内部使用.
-函数的形参就是局部变量.
- 全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存
- 局部变量:只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间
作用域链
代码都会有一个作用域,全局作用域,局部作用域,在局部作用域中还可以定义函数就又会产生一个局部作用域,根据内部函数可以访问外部函数变量这种机制,这种链式查找就叫做作用域链.
作用域链查找规则:采取就近原则来确定变量最终的值.
var a = 1;
function fn1() {
var a = 2;
var b = '22';
fn2();
function fn2() {
var a = 3;
fn3();
function fn3() {
var a = 4;
console.log(a); //a的值 4
console.log(b); //b的值 '22'
}
}
}
fn1();
预解析
JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。
* 预解析:在当前作用域下,JS代码执行前,浏览器会默认将带有var 声明的变量和 function 声明的函数在内存中进行提前声明定义.
console.log(num); // 结果是多少?
var num = 10; // undefined
注意:变量提升只提升声明,不提升赋值
fn();
function fn() {
console.log('打印');
}
注意:函数声明代表函数整体,所以函数提升后,函数名代表整个函数,但是函数并没有被调用!
//结果:报错提示 ”fn is not a function"
fn();
var fn = function() {
console.log('想不到吧');
}
该段代码执行之前,会做变量声明提升,fn在提升之后的值是undefined;而fn调用是在fn被赋值为函数体之前,此时fn的值是undefined,所以无法正确调用
对象
1.使用字面量创建对象:就是花括号 { } 里面包含了表达这个具体事物(对象)的属性和方法;{ } 里面采取键值对的形式表示
var star = {
name : 'pink',
age : 18,
sex : '男',
sayHi : function(){
alert('大家好啊~');
}
};
对象的使用
- 对象的属性
- 对象中存储具体数据的 "键值对"中的 "键"称为对象的属性,即对象中存储具体数据的项
- 对象的方法
- 对象中存储函数的 "键值对"中的 "键"称为对象的方法,即对象中存储函数的项
- 访问对象的属性
- 对象里面的属性调用 : 对象.属性名 ,这个小点 . 就理解为“ 的 ”
- 对象里面属性的另一种调用方式 : 对象[‘属性名’],注意方括号里面的属性必须加引号
console.log(star.name) // 调用名字属性
console.log(star['name']) // 调用名字属性
调用对象的方法
- 对象里面的方法调用:对象.方法名() ,注意这个方法名字后面一定加括号
star.sayHi(); // 调用 sayHi 方法,注意,一定不要忘记带后面的括号
- 变量、属性、函数、方法总结
属性是对象的一部分,而变量不是对象的一部分,变量是单独存储数据的容器 - 变量:单独声明赋值,单独存在
- 属性:对象里面的变量称为属性,不需要声明,用来描述该对象的特征
- 方法是对象的一部分,函数不是对象的一部分,函数是单独封装操作的容器
- 函数:单独存在的,通过“函数名()”的方式就可以调用
- 方法:对象里面的函数称为方法,方法不需要声明,使用“对象.方法名()”的方式就可以调用,方法用来描述该对象的行为和功能。
2.利用 new Object 创建对象
//这样创建的是一个空对象
var andy = new Obect();
给空对象添加属性和方法
- 通过对象操作属性和方法的方式,来为对象增加属性和方法
andy.name = 'pink';
andy.age = 18;
andy.sex = '男';
andy.sayHi = function(){
alert('大家好啊~');
}
3.使用构造函数创建对象
- 构造函数:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
- 构造函数的封装格式:
function 构造函数名(形参1,形参2,形参3) {
this.属性名1 = 参数1;
this.属性名2 = 参数2;
this.属性名3 = 参数3;
this.方法名 = 函数体;
}
var obj = new 构造函数名(实参1,实参2,实参3)
注意事项
- 构造函数约定首字母大写。
- 函数内的属性和方法前面需要添加 this ,表示当前对象的属性和方法。
- 构造函数中不需要 return 返回结果。
- 当我们创建对象的时候,必须用 new 来调用构造函数。
构造函数,如 Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(class)
创建对象,如 new Stars(),特指某一个,通过 new 关键字创建对象的过程我们也称为对象实例化
删除对象的属性
var a={"id":1,"name":"danlis"};
//添加属性
a.age=18;
console.log(a);
//结果:Object { id: 1, name: "danlis", age: 18 }
//修改属性
a.age="我怎么知道";
//结果:Object { id: 1, name: "danlis", age: "我怎么知道" }
delete a.age;
//结果:Object { id: 1, name: "danlis" }
new关键字的作用
- 在构造函数代码开始执行之前,创建一个空对象;
- 修改this的指向,把this指向创建出来的空对象;
- 执行函数的代码
- 在函数完成之后,返回this—即创建出来的对象
遍历对象
for…in 语句用于对数组或者对象的属性进行循环操作。
for (变量 in 对象名字) {
// 在此执行代码
}
var obj = {
name: 'zs',
age: 18,
sex: '男',
}
for (var k in obj) {
console.log(k); // 这里的 k 是属性名name,age,sex
console.log(obj[k]); // 这里的 obj[k] 是属性值'zs',18,'男'
console.log(obj
.k); //undifined,这里访问属性值一定要用[]的方式,因为k在这里是一个变量,如果用obj.k的方式系统会认为是在访问obj对象的k属性,没有k属性所以返回undifined
}
内置对象
Math对象
Math 对象不是构造函数,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用 Math 中的成员。
属性、方法名 功能
Math.PI 圆周率
Math.floor() 向下取整
Math.ceil() 向上取整
Math.round() 四舍五入版 就近取整 注意 -3.5 结果是 -3/ 3.5的结果是 4
Math.abs() 绝对值
Math.max()/Math.min() 求最大和最小值
Math.random() 获取范围在[0,1)内的随机值
获取指定范围内的随机整数:
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
日期对象
Date 对象和 Math 对象不一样,Date是一个构造函数,所以使用时需要实例化后才能使用其中具体方法和属性。Date 实例用来处理日期和时间
//获取当前时间的日期对象
var now = new Date();
//获取指定时间的日期对象
var future= new Date('2019/5/1');
获取总毫秒数
var now = new Date();
console.log(now.getTime());
console.log(now.valueOf());
console.log(+new Date());
console.log(Date.now());
数组对象
instanceof—可以判断一个对象是否是某个构造函数的实例
var arr = [1, 23];
var obj = {};
console.log(arr instanceof Array); // true
console.log(obj instanceof Array); // false
Array.isArray()—用于判断一个对象是否为数组对象
var arr = [1, 23];
var obj = {};
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false
数组常用的方法
注意:sort方法需要传入参数来设置升序、降序排序
- 如果传入“function(a,b){ return a-b;}”,则为升序
- 如果传入“function(a,b){ return b-a;}”,则为降序
注意,join()中如果不传入分隔符的参数默认按照,逗号拼接.
字符串对象
基本包装类型—就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法,可以方便操作.
字符串的不可变—当重新给字符串变量赋值的时候,变量之前保存的字符串不会被修改,依然在内存中。重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变。由于字符串的不可变,在大量拼接字符串的时候会有效率问题。
replace()方法----用于在字符串中用一些字符替换另一些字符
- 字符串.replace(被替换的字符串, 要替换为的字符串);,这个方法的第一个参数也可以传入正则表达式。
split()方法----用于切分字符串,它可以将字符串切分为数组。在切分完毕之后,返回的是一个新数组。
- 字符串.split(“分割字符”),如果传入‘’空字符串表示将字符串中的每个字符都分割成数组。
startsWith():表示参数字符串是否在原字符串的头部,返回布尔值
endsWith():表示参数字符串是否在原字符串的尾部,返回布尔值
let str = 'Hello world!';
str.startsWith('Hello') // true
str.endsWith('!') // true
repeat方法表示将原字符串重复n次,返回一个新字符串
'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
简单数据类型和复杂数据类型
简单类型(基本数据类型、值类型 ---- 在存储时变量中存储的是值本身,包括string ,number,boolean,undefined,null
复杂数据类型(引用类型)---- 在存储时变量中存储的仅仅是地址(引用),通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等;
栈(操作系统)---- 由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面
堆(操作系统)---- 存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
简单数据类型,值类型变量的数据直接存放在变量(栈空间)中
引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中
复杂数据类型传参
函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象