JavaScript基础入门
JavaScript 是运行在客户端的脚本语言
浏览器如何执行JS语句?
浏览器本身并不会执行JS代码,而是通过JS引擎来执行JS代码,JS引擎执行代码时逐行解释每一句源码(转换为机器语言),后由计算机执行,所以JS归为脚本语言。
浏览器分为渲染引擎和JS引擎
JS三部分组成:ECMAScript,DOM(文本对象模型).BOM(浏览器对象模型).
ECMAScript又称JS,实际上JS是ECMAScript语言的实现和扩展
DOM——文档对象模型
对页面各种元素进行操作
BOM——浏览器对象模型
对浏览器窗口进行操作,比如弹出框,控制浏览器跳转,获取分辨率等
JS书写位置:行内,内嵌,外部
<input type="button" value="点击" onclick="alert('OK')">
<script src="my.js"></script>
JS注释快捷键 单行注释:ctrl+/
多行注释:shift+alt+A
修改多行注释快捷键: ctrl+shift+/
JS输入和输出语句
alert(msg):浏览器弹出警示框
console.log(msg):浏览器控制台打印输出信息
console.log()和console.dir()的区别
prompt(info):浏览器弹出输入框,用户可以输入
JS常见弹出框
警告框:window.alert() 方法可以不带上window对象,直接使用alert()方法。
alert([content]): 【一个按钮】提示框 ,只有确定按钮
*提示框:****confirm([content]): 【两个按钮】提示框,里面既有确定按钮,也有取消按钮,我们可以定义一个变量来接收它的返回值,返回值为TRUE说明点击的是确定;
确认框:****prompt([content]):【两个按钮+输入框】提示框,在confirm基础上可以填写原因,填写的内容可以用变量接收,常见于某些留言本;
JS变量
变量是一个装东西的盒子,是用于存放数据的容器,我们通过变量名获取数据
变量的本质是程序在内存中申请的一块用来存放数据的空间
变量使用
声明一个变量并赋值,称之为变量的初始化
var age = 18;
变量语法扩展
更新变量:一个变量被重新赋值后,原有的值就会被覆盖,变量值将以最后一次赋的值为准
声明多个变量
同时声明多个变量,只需写一个var,变量之间使用英文逗号隔开。
var age =10,name = 'zs',sex = 2;
声明变量特殊情况
只声明,不赋值 ,结果为?即undefined
不声明,不赋值,直接使用某个变量会报错
不声明,直接赋值,可以使用,但不提倡
变量命名规范
变量交换
两个变量互换,需要一个临时变量来帮助实现,就如同我们必须先把右手的青苹果放到左手,此刻左手拿着青,红两种苹果,出现临时变量
var temp;
var apple1 = "A";
var apple2 = "B";
temp = apple1;//与数学相反,意思是把右边给左边,即给temp赋值为apple1的值A,即把A苹果放到桌上
apple1 = apple2; //苹果1被拿走,变量为空,得到苹果2的值“B”,即拿走B苹果
apple2 = temp;//被赋予temo的值,即apple2拿到桌子上的A苹果
变量小结
为什么需要变量?因为我们一些数据需要保存
变量是什么?变量就是一个容器,用来存放数据,方便我们以后使用
变量的本质?变量时内存里的一块空间,用来储存数据
变量如何使用?先声明变量,再赋值变量。 声明变量的本质是去内存申请空间
变量的初始化? 声明变量并赋值
变量命名规范有哪些?驼峰命名法,区分哪些变量不合法
交换变量思路?声明临时变量,交换赋值。
数据类型
不同数据所需占用的存储空间是不同的,为了便于区分,充分利用储存空间,定义了不同的数据类型,
数据类型是数据的类别型号
JS是一种弱类型语言或者说动态语言,所以不用提前声明变量类型,程序运行过程中,根据等号右边的值,类型会自动确定。
JS具有动态类型,即相同的变量可作不同的类型。
var x = 6;
var x = "Bill";
Number
在JS中八进制前面加0,十六进制前面加0x
数字类型最大值:console.log(Number.MAX_VALUES);
数字型的三个特殊值:alert(Infinity);
isNaN() 这个方法用来判断非数字,并且返回一个值(true,false)
console.log(isNaN(12));
String
JS可以用单引号嵌套双引号,或者用双引号嵌套单引号(外单内双,外双内单)
var srt = "夫'道德仁义礼',五者一体也。"
系统单(双)引号会自动匹配最近的单(双)引号,形成字符串
字符串内不能使用HTML的换行标识,需要使用字符串转义符,类似于HTML上的特殊字符,如
,
转义符都是\开头的,换行符:\n,缩进:\t,空格:\b,斜杠:\,单引号:\,双引号:*,都要写到引号里面
弹出网页警示框 alert(\n指另起一行);
String
检测获取字符串长度 length
var str = "aaaaaa";
console.log(str.length);
字符串拼接
多个字符串可以使用+进行拼接,拼接方式为:字符串+任何类型 = 拼接后的新字符串
拼接前会把与字符串相加的任何类型转换成字符串,再拼接一个新的字符串
只要有字符串和其它类型相拼接,最终结果是字符串类型
console.log('aa'+18); 输出aa18
console.log(12+12); 输出24
console.log('12'+12); 输出1212
+号口诀:数值相加,字符相连
变量和字符串相连口诀:引引加加
console.log('aa'+age+'岁');
变量不能加引号,加引号的变量会变成字符串
交互编程三要素
案例
var age = prompt('请输入年龄');
var str = '你今年'+age+'岁了';
alert(str);
Boolean
布尔型有两个值:true,false
布尔型与数字型相加时:true的值为1,false的值为0
undefined 和数字相加,最后的结果是 NaN
console.log(true+1); //输出结果为2
var set; //一个变量声明未赋值,就是undefine
console.log(set + "gg"); //输出结果为undefinedgg
var de = null;
console.log(de+'OK'); //输出结果为nullOK
console.log(de+1); //输出结果为1
获取数据类型:typeof可以用来检测变量的数据类型
var num = 18;
console.log(typeof num); //输出结果为 number
在浏览器控制台中,数字型为蓝色,字符串类型为黑色,深蓝色是布尔型,浅灰色是特殊字符
字面量是源代码中一个固定值的表示法,即字面来看如何表达这个值
数字字面量:1,2,3;字符串字面量:’小人‘;布尔:true;数组:[ ]
数据类型转换
转换为字符串
toString():
var num = 1;
alert(num.toString()); //toString和String两者位置不同
String()强制转换:
var num = 1;
alert(String(num));
与字符串加号拼接:
var num = 1;alert(num+' ');
toString()和String()使用方式不一样
日常更多使用第三种方式,也称之为隐式转换。
转换为数字型
parseInt(String)函数(转为整数数值)
parseFloat(string)函数(转换为浮点数数值)
Number()强制转换函数 Number(“12”);
js隐式转换(· * /)用算数运算隐式转化为数值型 ’12‘·0
var str = 'aaa';console.log(parseInt(str));
console.log(parseInt('3.14')); //取整
console.log(parseInt('3.94'));
console.log(parseInt(120px)); //120,去掉px单位
console.log(parseInt(rem120px)); //NaN
//parseFloat() 可以把字符型转换成数字型,得到的是小数点
console.log(parseFloat('3.14')); //取小数,3.14
console.log(parseFloat('120px')); //120,去掉px
console.log(parseFloat('rem120px')); //NaN
//Number() 强制转换
var er = "123';
console.log(Number(er));
//隐式转换(- * /)利用还是运算符,在算数运算时,JS自动转换了数据类型
console.log('123'-'120'); //结果为3,且转换成功
console.log(‘12’+0); //结果为12,且转换成功
案例:计算年龄
var year = prompt('出生年份');
var age = 2019 - year; //year取出的是字符串类型,但这里存在隐式转换
alert('今年'+age+'岁');
案例:加法器
var n1 = prompr("输入数");
var n2 = prompr("输入数");
var ty = parseFloat(n1)+parseFloat(n2);
alert('结果:'+ty);
转换为布尔型
Boolean函数,代表空,否定的值会被转换成false,如0,NaN,null,underfined;其余数都会被转换成true
console.log(Boolean(0)); //false
翻译器
计算机不能直接理解代码,需要用翻译器将代码翻译成机器语言。
翻译器有两种翻译方式:编译;解释。两者之间的区别在于翻译的时间点不同
编译器是在代码执行前进行编译,生成中间代码文件。【把所有菜做好,才能上桌吃饭】
解释器是在运行过程中进行及时解释,并立即执行(当编译器以解释方式运行时,也称解释器)【吃火锅,边吃边喝,同时进行】
标识符规范
标识符:指变量,属性,函数,参数的名字;不能是关键字或保留字。
关键字:JS本身已经使用了的字,不能再用他们作变量名,方法名。如break,case,catch,delete等。
保留字:未来的“关键字”,即现在还不是关键字,但未来有可能是关键字,所以不能使用他们作为变量名,方法名。boolean,Byte,char,class
Alt + Shift + 方向键:快速复制
运算符又称为操作符,是用于实现赋值,比较何执行算术运算符等功能的符号。
算术运算符:算术运算使用的符号,用于执行两个变量或值的运算符
(加+ ,减-,乘*,除/,取余数(取模)%)
最好在左右都打上空格 如:console.log(1 + 1);
取余:
console.log(5%3); // 2
console.log(4%2); // 0
console.log(3%5); // 3
浮点数的最高精度是17位小数,但在进行算术计算时其精确度远远不如整数
console.log(0.1+0.2); //0.3000000000000000004
console.log(0.07*100); //7.0000000000001
我们不能拿着浮点数来进行比较,是否相等
console.log(0.1 + 0.2 == 0.3); // false
由数字,运算符,变量等组成的式子,称之为表达式。
把我们右边表达式计算完毕,把返回值给左边:var num = 1 + 1;
2. 递增和递减运算符
递增(++)和递减(–)可以放置在变量前面,称之为前置递增,也可以放置在变量后面称之为后置递增。
递增和递减运算符必须和变量配合使用。
前置运算符:++num:num = num + 1;先 +1,后返回值
后置运算符:num++:num = num + 1;口诀:先返回原值参与运算,后自+1
var age = 10;
console.log(age++ +10); // 10+10 = 20,自增的运算符比加号运算符低
console.log(age); //11
前置递增和后置递增如果单独使用,效果是一样的
案例
var e = 10;
var f = e++ + ++e; //1. e++ = 10,e = 11; 2. ++e = 12,e = 12
alert(f);
比较运算符是两个数据进行比较所使用的运算符,比较运算后,会返回一个布尔值(true/false)作为比较运算的结果。
程序中的等于符号:== (默认转换数据类型),只要求值相等就可以
全等号:=== (全等要求值和数据类型都一致)
全不等号:!==
不等号:!= ,两个符号间不能留空格
console.log(18 == '18'); //true,**会默认将字符型转换为数字型,再进行比较**,判定是否相等
=:赋值,把右边给左边;:判断,判断两边值是否相等(此时有隐式转换);全等:=,判断两边的值和数据类型是否相等
逻辑运算符
逻辑运算符是进行布尔值运算的运算符,其返回值也是布尔值。后面开发中常用于多个条件的判断。
&&:逻辑与,and
两侧都为true,结果才是true,只要有一侧为false,结果就为false
console.log(3 > 5 && 3 > 2); // false
console.log(3 < 5 && 3 > 2); // true
||:逻辑或,or
两侧都为false,结果才是false,只要有一侧为true,结果就为true
console.log(3 > 5 || 3 > 2); // true
console.log(3 < 5 || 3 > 2); // false
!:逻辑非,not
console.log(!true); // false
短路运算(逻辑中断)
短路运算原理:当有多个表达式时左边的表达式值可以确定结果时,就不再运算右边表达式的值。
发现有多个表达式不是布尔值,而是一些值或者表达式
console.log(123&&456);
逻辑与&&短路运算口诀:
案例:
console.log(123 && 456); // 456 ,**数字中除0以外都为真**
console.log(0 && 456); // 0 ,**数字中0为假**
console.log(0&&456&&12*1212412); // 0
如果有空的或者否定的,为假的(0,‘ ’,null,undefined,NaN)其余是真的
如果发现前面这个值是假的,后面都不再运算,直接返回前面这个假值
如果前面这个值为真,则返回后面这个值
逻辑或短路运算口诀:
赋值运算符
赋值运算符:把数据赋值给变量的运算符
**num = num + 1; num++;**
**num = num + 2; num +=2;**
**var age = 2; age\* = 5;(age = age\*5 ); console.log(age); //10**
运算符优先级
**一元运算符里逻辑非优先级很高
流程控制
在一个程序执行过程中,各条代码的执行顺序对结果是有直接影响的
流程控制:控制我们的代码按照什么结构顺序来执行
三种结构:顺序结构,分支结构,循环结构,这三种结构代表三种代码执行的顺序
顺序流程控制
顺序结构是程序中最简单,最基本的流程控制,**没有特定语法结构,**程序会按照代码的先后顺序,依次执行,大多数代码都是这样执行的。
分支流程控制
在从上到下执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程),从而得到不同的结果。
if的语法结构:
if(条件表达式){
// 条件成立执行的代码语句
}
语句可以理解为一个行为,循环语句和分支语句就是典型的语句。一个程序由很多个语句组成,一般情况下,会分割为一个一个的语句。
案例:
var age = prompt('请输入您的年龄');
if(age >=18){
alert('我想你去浪漫的土耳其');
}
** 语法结构 if 结果 else 否则**
var age = prompt('请输入您的年龄');
if(age >=18){
alert('我想你去浪漫的土耳其');
}else{
alert('洗洗睡吧');}
//if里面的语句1 和 else里面的语句2, 最终只能有一个语句执行 2选1
//else 后面直接跟大括号
//案例:判断闰年
var year = prompt();
if(year%4==0&&year%100 !=0 || year%400 ==0){
alert("year is 闰 .");
}else{
alert("year isn't 闰 .");
}
** if else if 语句(多分支语句)**
语法规范:
if(条件表达式1){
// 语句1;
}else if(条件表达式2){
//语句2;
}else if(条件表达式3){
//语句3;
}else{
//最后的语句;
}
执行思路:
注意点:
案例:
//伪代码 按照从大到小判断的思路
//弹出prompt输入框,让用户输入分数,把这个值保存到变量中
使用多分支if else if 语句来分别判断输出不同的值
var score = prompt('输入分数');
if(score >= 90){
alert("出色");
}else if(score >= 80){
alert("真棒");
}else if(score >= 70){
alert("还行");
}else if(score >= 60){
alert("勉强");
}else{
alert("滚蛋");
}
三元表达式
由三元运算符组成的式子,称之为三元表达式
一元:++,–;++num
二元:3+5
三元:?,:
语法结构:条件表达式 ? 表达式1 :表达式2
三元表达式就是简化版的if … else 语句
执行思路:
如果条件表达式结果为真,则返回表达式1 的值;如果条件表达式结果为假,则返回表达式2的值。
案例:
var num = 10;
var result = num > 5 ? 'true' : ' false';
console.log(result); // true
案例2:
// 用户输入0~59之间的一个数字
//当数字小于10,则在这个数字前面补0拼接,否则不做操作
//用一个变量接受这个返回值
var t = prompt("输入0~59");
var r = t < 10 ? '0' + time : time;
alert(r);
分支流程控制switch语句
switch语句也是多分支语句,它用于基于不同的条件来执行不同的代码。当要针对变量设置一系列的特定值的选项时,就可以使用switch.
switch 语句也是多分支语句,也可以实现多选1
语法结构:switch : 转换,开关 ;case:例子或选项的意思
switch(表达式){
case value1:
执行语句1;
break;
case value2:
执行语句2;
break;
....
default:
执行最后的语句;
}
执行思路 :利用我们的表达式的值 和 case 后面的选项值相匹配,如果匹配上,就执行该case里面的语句,如果都没有匹配上,那么执行default里面的语句
switch(2){
case 1:
console.log('1');
break; //break很重要,是退出语句的意思
case 2:
console.log('2'); // 2
break;
case 3:
console.log('3');
break;
default:
console.log('NO');
}
switch语句更适合于处理变量特定值的语句,而变量带有范围,用else if 语句更好做。
switch注意事项
var num = 3;
switch(num){
case 1:
console.log('1');
break;
case 3:
console.log('3');
break;
}
案例:
var fruit = prompt("输入水果");
switch(fruit){
case '苹果':
alert('apple');
break;
case '橘子':
alert('orange');
break;
default:
alert('NO');
}
分支语句:switch语句和if else if 语句
两者区别:
循环语句
在程序中,一组被重复执行的语句被称之为循环体,能否继续执行,取决于循环的终止条件。由循环体及循环的终止条件组成的语句,称之为循环语句。
循环的目的:在实际问题中,有许多具有规律性的重复操作,因此在程序中要完成这类操作就需要可以重复执行某些代码。
for循环
for循环只要用于把某些代码循环若干次,通常跟计数有关。
语法结构:
for(初始化变量;条件表达式;操作表达式){
// 循环体
}
初始化变量:用var声明的一个普通变量,通常用于作为计数器使用
条件表达式:用来决定每一次循环是否继续进行,就是终止的条件
操作表达式:每次循环最后执行的代码,经常用于计数器变量更新(递增或递减)
// for循环可以执行相同的代码
for(var i = 1;i <= 100 ; i++){
console.log('Hello World'); // 我错了
}
运行过程:
案例:
// 可以让用户控制输出的次数
var num = prompt('输入次数');
for(var i = 0; i <= num ;i++){
console.log('Hello Word');
}
for循环重复不相同的代码
因为我们有计数器变量 i 的存在,i 每次循环值都会变化
案例:
for(var i = 1; i <= 100;i++){
if(i == 1){
console.log('他出生了');
}else if ( i == 100){
console.log('这个人今年百岁大寿‘);
}else{
console.log('这个人今年' + i + '岁了');
}
}
for循环重复某些相同的代码
for循环因为有了计数器的存在,我们还可以重复的执行某些操作,比如做一些算数运算。
// 案例:求1~100之间的整数累加和
var sum = 0;
for(var i = 1;i <=100;i++){
sum + = i ; //sum = sum +i ;
}
alert(sum);
//求1~100之间所有数的平均值
var ave = 0;
ave = sum / 100 ;
alert(ave);
// 求1~100之间所有偶数和奇数的和
var even = 0;
var odd = 0;
for(var i = 1;i <= 100;i++){
if(i%2 == 0){
even = even + i;
}else{
odd = odd + i;
}
}
alert('偶数和' + even);
alert('奇数和' + odd);
//求1~100之间所有能被3整除的数字的和
var result = 0;
for(var i = 1;i <=100;i++){
if(i%3 == 0){
result = result + i;
}
}
alert('被3整除的数字的和是:' + result);
//学生成绩
var num = prompt('请输入班级总人数:'); //弹出框为班级总人数
var sum = 0; //求和的变
var average = 0; //求平均值的变量
for(var i = 1;i <=num;i++){
var score = prompt('请输入第'+ i + '个学生成绩');//依次输入学生的成绩(保存score),用到for循环
//因为从prompt取过来的数据是 字符串型的需要转换为数字型
sum = sum +parseFloat(sore);//0+学生成绩
}
aveage = sum/num;
alert('班级总成绩'+ sum);
alert('班级平均分' + aveage);
案例:打印星星
for(var i = 0;i<=100;i++){
console.log("★");
}
//采取追加字符串的方式,可以一行打印到控制台上
var str = ''";
for(var i = 1; i<=5;i++){
str = str + '★';
}
console.log(str);
双重for循环
循环嵌套是指在一个循环语句中在定义一个循环语句的语法结构,如在for循环语句中,再嵌套一个for循环。
语法结构:
for(外层的初始化变量;外侧的条件表达式,外层的操作表达式){
for(内层的初始化变量;内侧的条件表达式,内层的操作表达式){
//执行语句;
}
}
// 1. 将里面的循环看做外层循环的语句
// 2. 外层执行一次,里层执行全部
代码验证
for(var i = 1;i<=3;i++){
console.log('外' + i + '次');
for (var j = 1; j<= 3; j++){
console.log('里'+ j +'次');
}
}
//案例:打印5行星星
var str1 = '';
for(var i = 1;i<=5;i++){
for (var j = 1; j<= 5; j++){
str1 = str1 + '★';
}
str1 = str1 + '\n';//要换行,不然会出现在一行
}
console.log(str1);
//案例:打印倒三角
var str1 = '';
for(var i = 1;i<=10;i++){
for (var j = i; j<= 10; j++){
str1 = str1 + '★';
}
str1 = str1 + '\n';//要换行,不然会出现在一行
}
console.log(str1);
//案例:九九乘法表
//一共有9行,每行个数不一样,需要双重for循环
//外层for 循环控制行数i,打印9行
//内层for循环控制每行公式 j
//核心算法:每一行公式的个数正好和行数一致,j<=i
//每行打印完毕都需要重新换一行
var str1 = '';
for(var i = 1;i<=9;i++){//外层控制行数 i
for (var j = 1; j<= i; j++){ //内层行数内容,列数
//1 X 2 = 2
str1 = str1 + i + 'x' + j + '=' + i * j;
}
str1 = str1 + '\n';// str += '\n';
//要换行,不然会出现在一行
}
console.log(str1);
for循环总结
断点调试
断点调试可以****帮我们观察程序的运行过程
浏览器-----F12-----Sources-----打断点(程序运行到这里会停止)------刷新(程序运行)----F11(查看程序运行步骤)-----再次点击断点,取消 -----刷新(直接运行)
JS_2019.10.30
while循环
while语句可以在条件表达式为真的前提下,循环执行指定的一段代码,直到表达式不为真时结束循环。
while语句语法结构: while 当…的时候
while(条件表达式){
//循环体代码
}
执行思路:
代码验证
var num = 1;
while(num <= 100){
console.log('OK'); //操作表达式
num++;//计数器
}
里面也需要计数器 ,初始化变量
里面也应有操作表达式 ,完成计数器的更新,防止死循环
案例:计算1~100 之间所有整数的和
var sum = 0;
var i = 1;
while(i <= 100){
sum += i;
i++;
}
console.log(sum);
案例:提示框
var message = prompt('你聪明吗?');
while (message !=='不聪明') {
message = prompt('聪明');
}
alert('还算有自知自明');
do…while循环
do…while语句是while语句的一个变体。该循环会先执行一次代码块,然后对条件表达式进行判断,如果为真,就会重复执行,否则退出循环。
语法结构:
do{
//循环体代码 条件为true时重复执行循环体代码
}while(条件表达式);
执行思路:do…while与while不同的是do…while先执行一次循环体,再判断条件。
先执行循环体,再判断,do…while 循环体至少执行一次循环体代码
代码验证:
var j = 1;
do{
console.log('how are you?');
j++;
}while(j<=100);
**案例:**计算1~100 之间所有整数的和
var sum = 0;
var i = 1;
do{
sum += i;
i++;
}while(i <= 100);
console.log(sum);
do…while循环总结
continue和break
continue关键字用于立即跳出本次循环,继续下一次循环(本次循环体中continue之后的代码就会少执行一次)
continue 关键字 退出本次(当前次的循环),继续执行剩余次数循环
吃五个包子,吃到第三个发现有虫子,扔掉,继续吃第4个,第5个。
for(var i = 1;i <= 5; i++){
if (i == 3) { // 第三个包子有虫子扔掉
continue; // 只要遇见 continue就退出本次循环 直接跳到 i++
}
console.log('我正在吃第'+ i + '包子');
}
案例:求1~100之间,除了能被7整除之外的整数和
var sum = 0;
for (var i = 0;i <=100; i++){
if(i%7 == 0){
continue;
}
sum += i;
}
console.log(sum);
吃五个包子,吃到第三个发现有虫子,扔掉,其余的不吃了。
for(var i = 1;i <= 5; i++){
if (i == 3) { // 第三个包子有虫子扔掉
break; // 只要遇见 break就退出本次循环 for循环也不再执行
}
console.log('我正在吃第'+ i + '包子');
}
标识符命名规范
操作符规范
单行注释规范
单行注释前面注意有个空格
循环语句左右两侧各有一个空格 for (var i = 1 ; i <= 5 ; i++) {}
数组
数组是指一组数据的集合,其中每个数据被称为元素,在数组中可储存任意类型的元素,数组是一种将一组数据存储在单个变量名下的优雅方式。(作用)
之前学习的变量只能储存一个值,而数组(Array)可以把一组相关的数据一起存放,并方便访问(获取)方式。
// 普通变量一次只能储存一个值
var num = 10;
// 数组一次可以储存多个值
var arr = [1,2,3,4] ;
JS中创建数组方式:
1. 利用new创建数组
var arr(数组名) = new Array(); // 创建一个新的空数组 ,注意A要大写
arr[0] = "ps";
2. 利用数组字面量创建数组(常用)
var arr = ['a','b','c','d']; // 使用数组字面量方式创建带初始值的数组
// 数字内数据一定用逗号分隔,数组里面数据称之为数组元素
// 数组的字面量是方括号[ ]
// 声明数组并赋值称之为数组的初始化
获取数组中的元素
数组索引,索引(下标):用来访问数组元素的序号(数组下标从0开始)。
var arr = ['a','b','c','d'];
//索引号: 0 1 2 3
数组可以通过索引来访问,设置,修改对应的数组元素,我们可以通过"数组名[索引]"的形式来获取数组中的元素。
取出数组的某一项:数组名[索引]
从数组中取出每一个元素时,代码是重复的,不一样的是索引值在递增
console.log (arr[1]); // b
console.log (arr[2]); // c
console.log (arr[4]); // 因为没有这个数组元素 ,所以输出的是 undefined
遍历数组
遍历:把数组中的每个元素从头到尾都访问一次(类似早点名)。
输出数组所有元素通过循环
var arr = ['a','b','c','d'];
for (var i = 0; i < 4 ; i++) { // 因为我们的数组**索引号从0开始**,所以 i 必须从 0 开始 i < 4
console.log(arr[i]); // 输出的时候 arr[i] i 是索引号当计数器来用
}
数组的长度
使用"数组名.length"可以访问数组元素的数量(数组长度)。
for (var i = 0; i < arr.length ; i++) { // arr.length 动态监测数组元素的个数,添加元素后也可准确遍历
console.log(arr[i] );
}
console.log(arr.length); // 数组长度是元素个数 ,不要跟索引号混淆
数组索引和数组长度关系:数组索引号从0开始, 数组长度是元素个数
案例:数组求和及平均值
//执行思路:
// 声明一个求和变量 sum
// 遍历这个数组,把里面每个数组元素加到sum里面
// 用求和变量sum除以数组的长度就可以得到数组的平均值
var arr = [2,6,1,7,4];
var sum = 0;
var average = 0;
for(var i = 0;i < arr.length;i++){
sum += arr[i]; //+ 的是数组元素arr[i],不是计数器i
}
average = sum / arr.length;
console.log(sum,average); //先要输出多个变量,用逗号分隔即可
案例:取数组最大值
//执行思路:
// 声明一个保存最大元素的变量 max
// 默认最大值可以去数组中第一个元素
// 遍历这个数组,把里面每个元素和 max 相比较
// 如果这个数组元素大于max 就把这个元素存到max里面,否则进行下一轮比较
// 输出max
var arr = [2,6,1,7,4];
var max = arr[0];
for(var i = 1;i < arr.length;i++){
if(arr[i]>max){max = arr[i];}
}
console.log('最大值是' + max);
案例:把数组转换为字符串
//执行思路:
// 需要一个新变量用于存放转换完的字符串 str
// 遍历原来的数组,分别把里面的数据取出来,加到字符串里面
// 同时在后面加一个分隔符
var arr2 = ["red","green","blue","pink"];
var str = '';
var sep = ']';
for(var i = 0;i<arr.length;i++){
str += arr[i] + sep;
}
console.log(str);
*** 数组中新增元素**
可以通过修改length长度以及索引号增加数组元素
但只能为空
var arr2 = ["red","green","blue","pink"];
arr.length = 5;
console.log(arr2);
console.log(arr[4]); //undefine
console.log(arr[5]) //undefine
// 其中索引号是4,5的空间没有给值,就是声明变量未赋值,默认值为undefined
可以通过修改数组索引的方式追加数组元素(最常用)
// 不能直接给数组名赋值,否则会覆盖掉以前的元素
arr2[4] = "oppo";
arr2[5] = "vivo";
console.log(arr2);
arr2[0] = "huawei"; //这里会替换原来的数组元素
console.log(arr[0]);
console.log(arr[4]); //undefine
console.log(arr[5])
arr2 = "you";
console.log(arr2); //不要直接给数组名赋值,否则里面的数组元素都没有了
案例:在数组中依次加入1~10整数
// 新建一个数组,里面存放10个整数
// 核心原理:使用循环来追加数组
// 声明一个空数组
// 循环中的计数器 i 可以做为数组元素存入
// 由于数组的索引号是从0开始的,因此计数器从0开始更为合适,存入的数组元素要+1
var arr3 = [];
for(var i = 0; i< 10;i++){
// arr = i; 不要直接给数组名赋值,否则以前的元素都没了
arr[i] = i + 1;
}
console.log(arr3);
案例:筛选数组,将数组中大于等于10的元素选出来,放入新数组
// 声明一个新的数组用于存放新数据newArr
// 遍历原来的旧数组,找出大于等于10的元素
// 依次追加给新数组newArr
var arr4 = [2,3,4,5,6,45,23,12,78,11,10];
var newArr = [];
var j = 0;
for(var i = 0;i < arr4.length;i++){
if(arr4[i] > 10){
//新数组应该从0开始,依次递增
newArr[j] = arr4[i];
j++;
}
}
console.log(newArr);
// 方法2
var arr4 = [2,3,4,5,6,45,23,12,78,11,10];
var newArr = [];
for(var i = 0;i < arr4.length;i++){
if(arr4[i] > 10){
//新数组应该从0开始,依次递增
newArr[newArr.length] = arr4[i];
}
}
console.log(newArr);
案例:删除指定数组元素
将数组中的0去掉后,形成一个不包含0的新数组
// 需要一个新数组用于存放筛选之后的数据
// 遍历原来的数组,把不是0的数据添加到新数组里面(此时要注意采用数组名 + 索引的格式接收数据)
// 数组里面的个数,用length不断累加
var arr5 = [2,3,4,5,6,0,45,23,12,78,11,10,0];
var newArr1 = [];
for(var i = 0;i < arr5.length;i++){
if (arr5[i]!=0) {
newArr1[newArr1.length] = arr5[i];
}
}
console.log(newArr1);
案例:翻转数组
// 声明一个新数组 newArr2
// 把旧数组索引号第4个取过来(arr6.length - 1),给新数组索引号第0个元素 (newArr2.length)
// 采取递减的方法 i--
var arr6 = ["red","green","blue","pink"];
var newArr2 = [];
for(var i = arr6.length - 1;i >= 0 ;i--){
newArr2[newArr2.length] = arr6[i];
}
console.log(newArr2);
案例:数组排序(冒泡排序)
// 交换两个变量
var num1 = 'A';
var num2 = 'B';
var temo;
temp = num1; //num1的值赋给temp
num1 = num2;
num2 = temp;
console.log(num1,num2);
**冒泡排序是一种简单的排序算法,把一系列的数据按照一定的顺序进行排列显示,重复地走访要排序的数列,**一次比较两个元素,如果他们的顺序错误即将他们交换过来。
走访数列的工作是重复地进行直到没有再需要交换,也就是数列已经排序完成。
这个名称是因为越小的元素会经由交换慢慢"浮"到数列顶端。
案例分析: 5 4 3 2 1
长度 是 数组长度 减去 次数
2. 每一次交换次数,用里层for循环
第1趟 交换4次
第2趟 交换3次
第3趟 交换2次
第4趟 交换1次
长度 是 数组长度 减去 次数
但因为次数从0开始 所以最终 arr.length - i - 1
3. 每次交换2个变量
var arr7 = [5,4,3,2,1];
for(var i = 0;i < arr7.length -1 ;i++){
for(var j = 0; j <= arr7.length - i - 1;j++ ){ //里面的循环体。每一趟的交换次数
if(arr7[j] > arr7[j + 1]){ //内部交换2个变量的值 前一个和后一个数组元素相比较
var temp = arr7[j];
arr7[j] = arr7[j + 1];
arr7[j + 1] = temp;
}
}
} // [1,2,3,4,5]
var arr7 = [5,4,3,2,1];
for(var i = 0;i < arr7.length -1 ;i++){
for(var j = 0; j <= arr7.length - i - 1;j++ ){ //里面的循环体。每一趟的交换次数
if(arr7[j] < arr7[j + 1]){ //内部交换2个变量的值 前一个和后一个数组元素相比较
var temp = arr7[j];
arr7[j] = arr7[j + 1];
arr7[j + 1] = temp;
}
}
} // [5,4,3,2,1]
函数
函数的概念
for循环语句也能实现一些简单的重复操作,但是比较有局限性,此时可以使用JS中的函数。
函数:封装了一段可被重复调用执行的代码块,通过此代码块可以实现大量代码俄重复使用。
案例:求10~50的累加和
var sum = 0;
for(var i =10);i <= 50);i++{
sum += i;
}
console.log(sum);
方法二:
//函数就是封装了一段可以被重复执行的代码块
//目的:让大量代码重复使用
function getSum(num1,num2){
var sum = 0;
for(var i = num1;i<num2;i++){
sum += i;
}
console.log(sum);
}
getSum(1,100);
get(10,50);
函数使用
函数使用分为两步
声明函数
function 函数名(){
// 函数体
}
代码验证:
function say(){
console.log('hello');
}
A. function 声明函数的关键字 全部必须小写
B. 函数是做某件事情,一般是为了实现某个功能才定义的,所以通常我们将函数名命名为动词,函数名一般是动词 say
C. 声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码
调用函数
函数名();// 通过调用函数名来执行函数体代码
getSum(10,50);
A. 调用的时候千万不要忘记加小括号
B. 口诀:函数不调用,自己不执行
案例:利用函数计算1~100之间的累加和
function getSum(num1,num2){
var sum = 0;
for( var i = num1 ; i <= num2 ; i++ ){
sum = sum + i;
}
console.log(sum);
}
getSum(1,100);
函数封装
函数封装是把一个或多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口。
白话文:封装类似于将电脑配件整合组装到机箱中(类似于快递打包)
函数参数
函数可以重复相同代码 say(); //helllo
可以利用函数的参数实现函数重复不同的代码
形式上的参数,函数定义的时候,传递的参数 ,当前并不知道是什么
function(形参1,形参2…){ // 在声明函数的小括号里面是 形参(形式上的参数)}
实际上的参数,函数调用的时候传递的参数,实参是传递给形参的
function(实参1,实参2…){ // 在函数调用的小括号里面是 实参(实际的参数)}
function cook(aru){ //**形参是接收实参的** aru = '番茄炒蛋' 形参类似于一个变量
console.log(aru);
}
cook('番茄炒蛋');
案例
利用函数求任意两个数的和
function getSum(num1,num2){
console.log(num1+num2);
}
getSum(1,3);
利用函数求任意两个数之间的和
function getSum(start,end){
var sum = 0;
for(var i = start;i<=end;i++){
sum += i;
}
console.log(sum);
}
getSum(1,100);
//函数形参和实参不匹配
function getSum(num1,num2){
console.log(num1+num2);
}
// 实参与形参的个数一致,则正常输出结果
getSum(1,3);
// 如果实参的个数多于形参的个数 会取到形参的个数
getSum(1,2,3); // 则3不再参与运算
// 如果实参的个数少于形参的个数 多出的形参会定义为undefined 结果为NaN
getSum(1); // 形参可以看作是不用声明的变量 num2是一个变量但没有接收值 var num2 = ' ' = undefined 即 1+undefined = NaN
总结
函数的返回值
函数内部不应该有输出语句(函数值返回到外部–厨师应当把菜端出)
将函数值返回给调用者
return语句
function 函数名(){
return 需要返回的结果;
}
函数名();
代码验证:
function getResult(){
return 666;
}
getResult();
console.log(getResult()); //666
function cook(aru){ //形参是接收实参的 aru = '番茄炒蛋' 形参类似于一个变量
return cook;
}
console.log(cook('番茄炒蛋'));
案例:
// 利用函数 求两个数的最大值
function getMax(num1,num2){
/*if(num1 > num2){
return num1;
}else{
return num2;
}*/
return num1 > num2 ? num1:num2;
}
console.log(getMax(1,3));
//利用函数 求数组[5,2,99,101,67,77]中的最大数值
functon getArrMax(arr){
var max = arr[0];
for(var i = 1; i <= arr.length;i++){
if(arr[i] > max){
max = arr[i];
}
}
return max;
}
// getArrMax([5,2,99,101,67,77]); 实参是一个数组送过去
// 实际开发中,我们经常用一个变量来接受函数的返回结果,使用更简单
var re = getArrMax([5,2,99,101,67,77]);
console.log(re);
**return 终止函数**
// return语句后代码不再被执行
function cook(aru){
return cook;
alert('不再被执行!');
}
console.log(cook('番茄炒蛋'));
// return只能返回一个值,如果逗号隔开多个值,以最后一个为准
function fn(num1,num2){
return num1,num2; //返回的结果是最后一个值
}
console.log(fn(1,2)); // 2
// 当需要输出多个数值,可以使用数组
function getResult(num1,num2){
return [num1 + num2 ,num1 - num2 ,num1 * num2 ,num1 /num2 ];
}
var re = getResult(1,2);
console.log(re);
// 函数如果有return 则返回的是return后面的值;如果函数没有return 则返回undefined
function fun1(){
return 666;
}
console.log(fun1()); // 666
function fun2(){
}
console.log(fun2()); // undefined
break,continue,return的区别
通过榨汁机看透函数
榨汁机 函数
输入原料 function fn (参数1,参数2){ // 输入参数
内部处理 函数体; // 内部处理
输出果汁 return 返回值; // 返回结果
arguments的使用
当不确定有多少个参数传递时,可以用arguments来获取。在JS中,arguments实际上是当前函数的一个内置对象。所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参。
function fn(){
console.log(arguments); // 里面存储了传递过来的所有实参
console.log(arguments.length);
console.log(arguments[2]); // 1,2,3
// 我们可以按照数组的方式进行遍历
for(var i = 0 ; i <argument.length;i++){
console.log(argument[i]); //1,2,3,4,5
}
}
fn(1,2,3);
fn(1,2,3,4,5);
arguments展示形式是一个伪数组,因此可以进行遍历
伪数组具有如下特点:
案例:
//利用函数 求任意个数的最大值
functon getMax(){
var max = arguments[0];
for(var i = 1; i < argument.length;i++){
if(argument[i] > max){
max = argument[i];
}
}
return max;
}
console.log(getMax(1,2,3));
console.log(getMax(1,2,3,4));
//翻转任意数组 reverse 翻转
function reverse(arr){
var newArr = [];
for(var i = arr.length - 1;i >= 0;i--){
newArr[newArr.length] = arr[i];
}
return newArr;
}
var arr1 = reverse([5,2,99,101,67,77]);
console.log(arr1); //[77,67,101,99,2,5]
var arr2 = reverse(['red','pink','blue']);
console.log(arr2);
//利用函数冒泡排序 sort排序
function sort(arr){
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;
}
}
}
return arr;
}
var arr1 = sort([5,2,99,101,67,77]);
// 利用函数判断闰年
function isYear(year){
var flag = false;
if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0){
flag = true;
}
return flag;
}
console.log(isYear(2000));
函数可以调用另外一个函数
因为每个函数都是独立的代码块,用于完成特殊任务,因此经常会用到函数相互调用的情况。
案例:
//函数可以互相调用
function fn1(){
console.log(11);
fn2(); // 在fn1函数里面调用了 fn2函数
}
fn1();
function fn2(){
console.log(22);
}
//打印结果 11 22
// 用户输入年份,输出当前年份2月份的天数
function backDay(){
var year = prompt('请您输入年份:');
if(isYear(year)){ //调用函数加小括号()
alert('闰年2月份29天');
}else {
alert('平年2月份28天');
}
}
backDay();
// 利用函数判断闰年
function isYear(year){
var flag = false;
if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0){
flag = true;
}
return flag;
}
console.log(isYear(2000));
函数的两种声明方式
利用函数关键字自定义函数(命名函数)
这种是函数声明 ,可以先使用后定义 ,它会对函数的声明进行一个提升
function fn(){
}
fn();
函数表达式(匿名函数)
这种叫做函数表达式 ,必须先定义后使用
//var 变量名 = function() {};
var fun = functon(aru){
console.log('我是函数表达式');
console.log(aru);
}
fun('换笔记');// 打印结果 我是函数表达式 换笔记
A. fun是变量名,不是函数名
B. 函数表达式声明方式跟声明变量差不多,只不过变量里面存的是值,而函数表达式里面存的是函数
C. 函数表达式也可以进行传递参数
fun();
var fun=function(){
console.log("本事啦,我的弟");//Uncaught TypeError: fun is not a function
}
直接使用fun则会报一个”Uncaught ReferenceError: fun is not defined”的错误(和不声明fun报错是不一样的),其实fun也是一个变量,只不过他是function(){console.log(“本事啦,我的弟”);}的一个引用,fun的声明被提升了,但是初始化没有被提升。
JS作用域
作用域概述
一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
// js作用域:是代码名字(变量)在某个范围内起作用和效果,目的是提高程序的可靠性,更重要的是减少命名冲突
// js作用域(es6)之前: 全局作用域 局部作用域
// 全局作用域:整个script标签 或者是一个单独的js文件
var num = 10;
console.log(num);
//局部作用域(函数作用域):在函数内部就是局部作用域,这个代码的名字只在函数内部起效果和作用
function fn(){
//局部作用域
var num = 20;
console.log(num);
}
fn();
//打印结果 10 20 虽然命名相同,但在不同作用域下,所以两者不影响
变量作用域分类
根据作用域的不同,变量可以分为
全局变量
// 全局变量:在全局作用域下的变量,在全局下都可以使用(在函数外定义的变量)
// 如果在函数内部 ,没有声明直接赋值的变量也属于全局变量
var num = 10; // num就是一个全局变量
console.log(num);
function fn(){
console.log(num);
}
fn();
局部变量
// 局部变量:在局部作用域下的变量 , 后者在函数内部的变量就是局部变量(函数内部定义的变量)
// 在函数内部var声明的变量是局部变量
// 函数的形参实际上就是是局部变量 aru
function fun(aru){
var num1 = 10; //num1就是局部变量 只能在函数内部使用
num2 = 20;
}
fun();
console.log(num1); //报错,局部变量无法在外部被调用
console.log(num2); //20
从执行效率来看全局变量和局部变量
JS没有块级作用域
// 现阶段我们js没有块级作用域
// JS也是在es6的时候新增的块级作用域
// 块级作用域就是用{}进行包含的 if{} for{}
// 在java中
// if(xx){int num = 10;} 外面是不能调用的
if(3>5){
var num = 10;
}
console.log(num); //10
//由于现阶段js没有块状作用域 ,所以变量放在内外都可以使用
JS也是在es6的时候新增的块级作用域
块级变量和局部变量的区别
局部变量是函数内部的变量,函数运行完毕后局部变量会被销毁;块级变量是在代码块中的变量,不是函数内,也不是全局的。
作用域链
//作用域链 : 内部函数访问外部函数的变量,采取的是链式查找的方式来决定取哪个值,这种结构我们称之为作用域链 就近原则
var num = 10; //写了一行代码就有作用域,是全局作用域
function fun(){ //外部函数
var num = 20;
function fn(){ //内部函数
console.log(num); // 20 ,就近原则
}
fn();
}
fun();
//案例1:结果是几?
function f1(){
var num = 123;
function f2(){
var num = 0;
console.log(num); //0,站在目标出发,一层一层地往外查找
}
f2();
}
var num = 456;
f1();
JS预解析
js引擎运行分为两步:预解析 代码执行
预解析分为变量预解析(变量提升)和 函数预解析(函数提升)
//未赋值
console.log(num); //undefined
//
console.log(num); //undefined
var num = 10;
//相当于执行了以下代码
/*var num; //变量提升,未赋值
console.log(num);
num = 10;*/
//
fn();
function fn(){ // 变量声明
console.log(11); //11
}
//预解析会将所有变量声明提升到当前作用域的最前面
//
fun(); // 报错
var fun = function(){ //该表达式是函数声明的形式
console.log(22);
}
//相当于执行了以下代码
var fun; //声明变量,未赋值
fun();
fun = functon(){
console.log(22);
} // fun();上面的代码没有这个函数的方法,所以报错
//函数表达式调用必须写在函数表达式下
预解析案例:
var num = 10;
f1();
function f1(){
console.log(num);
var num = 20;
}
//相当于以下代码(变量提升后的结果)
var num;
function f1(){ //f1也是一个作用域,需要变量提升
var num; //未赋值,就近原则
console.log(num); //undefined
num = 20;
}
num = 10;
f1();
var num = 10;
function f1(){
console.log(num);
var num = 20;
console.log(num);
}
f1();
//相当于以下代码(变量提升后的结果)
var num;
function f1(){ //f1也是一个作用域,需要变量提升
var num; //未赋值,就近原则
console.log(num); //undefined
num = 20;
console.log(num); //20
}
num = 10;
f1();
var a = 18;
f1();
function f1(){
var b = 9;
console.log(a);
console.log(b);
var a = 123;
}
//相当于以下代码
var a;
function f1(){
var b; // 未赋值
var a;
b = 9;
console.log(a); //undefined
console.log(b); //9
a = '123';
}
a=18;
f1();
f1();
console.log(a);
console.log(b);
console.log(c);
function f1(){
var a = b = c = 9;
//相当于var a = 9;b = 9;c= 9;
//b和c直接赋值,没有var声明,当全局变量看
//集体声明:var a = 9,b = 9,c = 9;
console.log(a);
console.log(b);
console.log(c);
}
//以下代码
function f1(){
var a ; //a加了var,属于局部变量
a = b = c = 9;
//相当于var a = 9;b = 9;c= 9;
//b和c直接赋值,没有var声明,当全局变量看(全局变量任何地方都能使用)
//集体声明:var a = 9,b = 9,c = 9;
console.log(a); //9
console.log(b); //9
console.log(c); //9
}
f1();
console.log(a); //报错
console.log(b); //9
console.log(c); //9
JS对象
什么是对象
现实生活中,对象是一个具体的事物,看得见摸得着的实物,如一本书,一辆车
在JS中,对象是一组无序相关属性和方法的集合,所有事物都是对象,如字符串,数值,数组,函数等。
对象由属性和方法组成
属性:事物的特征,在对象中用属性来表示(常用名称)
方法:事物的行为,在对象中用方法来表示
(常用动词)
举例:手机的大小,颜色,重量(属性);打电话,发短信(方法)
保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组。
举例:保存一个人的个人信息在数组中方式为
var arr = ['张三','男',12,154];
JS中的对象表达结构更清晰,更强大
person.name = '张三';
person.sex = '男';
person.age = 12;
person.height = 154;
利用字面量创建对象
对象字面量:{ }里面包含了表达这个具体事物(对象)的属性和方法
键:相当于属性名
值:相当于属性值,可以是任意类型的值(数字类型,字符串类型,布尔类型,函数类型等)
//1. var obj = {};//创建一个空的对象
var obj = {
uname:'张三',
age :18,
sex:'男',
sayHi:functon(){
console.log('hello');
}
}
//里面的属性或方法我们采用键值对的形式 键 属性名 :值 属性名
//多个属性或者方法中间用逗号隔开
//方法冒号后面跟的是一个匿名函数
//2.使用对象
//调用对象的属性,我们采用 对象名.属性名,这个小点.我们理解为 "的"
console.log(obj.uname); //张三
//调用属性还有一种方法:对象名['属性名'],注意方括号里面必须加引号
console.log(obj['age']); //18
//调用对象的方法sayHi() 对象里面的方法调用:对象名.方法名()
//千万别忘记添加小括号
obj.sayHi(); //hello
变量,属性,函数,方法的区别
//1.变量和属性相同时,他们都是用来存储数据的
//变量 单独声明并赋值,使用的时候必须是 对象.属性
//变量和函数可以直接写,而属性和方法一定要加一个对象
var num = 10;
var obj = { //对象
age:18; //属性
fn:function(){ //方法
}
}
function fn(){ //函数
}
console.log(obj.age); //18
console.log(age); //报错
//2.函数和方法的相同点 都是实现某种功能 做某件事
//函数是单独声明并调用的,函数名()单独存在的方法在对象里面,调用的时候 对象.方法()
利用new Object 创建对象
// 利用 new Object 创建对象
var obj = new Object();
obj.uname = '张三';
obj.age = 18;
obj.sex = '男';
obj.sayHi = function(){
console.log('hello');
}
//利用等号 = 赋值的方法,添加对象的属性和方法
//每个属性和方法之间用分号结束
console.log(obj.uname); //张三
console.log(onj['sex']); //男
obj.sayHi(); //hello
利用构造函数创建对象
为什么需要使用构造函数?
因为前面两种创建对象的方式一次只能创建一个对象
//因为我们一次创建一个函数,里面很多的属性和方法是大量相同的,只能复制
//因此我们可以利用函数的方法,重复这些相同的代码,我们称之为构造函数
//又因为这个函数不同,里面封装的不是普通代码,而是对象
//构造函数,就是把对象里面一些相同的属性和方法抽象出来封装到函数里面
//案例运用:创建四大天王的对象 相同属性:名字 年龄 性别 相同方法:唱歌
var ldh = {
uname:"刘德华",
age:55,
sing:function(){
console.log('冰雨');
}
}
var zxy = {
uname:"张学友",
age:58,
sing:function(){
console.log('李香兰');
}
}
构造函数:一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new运算符一起使用。
我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
语法格式:
function 构造函数名( ){
this.属性 = 值;
this.方法 = function( )
}
new.构造函数值();
案例优化后:
//1.构造函数名字首字母要大写
function Star(uname,age,sex){
//5.属性和方法前面必须添加 this
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function (song) {
console.log(song);
}
}
//2.构造函数不需要return,就可以返回结果
var ldh = new Star('刘德华',18,'男'); //调用函数返回的是一个对象
//3.调用构造函数,必须使用new
//4.如下,只要new Star() 调用函数就创建一个对象 ldh{}
var zxy = new Star('张学友',19,'男');
//console.log(typeod ldh); 判断lah变量的类型
console.log(ldh.name); //刘德华
console.log(ldh.age); //18
console.log(ldh['sex']); //男
ldh.sing('冰雨'); //向上传回一个实参 打印:冰雨
构造函数和对象的区别
构造函数,如Star( ),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(class)
—— 汽车设计图纸
创建对象,如new Star( ),特指某一个,通过new关键字创建对象的过程也称为对象的实例化
—— 宝马车
// 构造函数和对象
//1.构造函数 泛指的某一大类,类似于java语言里的类(class);如明星,也是指一大批人
function Star(uname,age,sex){
//属性和方法前面必须添加 this
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function (song) {
console.log(song);
}
}
//2.对象 是特指一个具体的事物,如刘德华
var ldh = new Star('刘德华',18,'男'); //调用函数返回的是一个对象
console.log(ldh); // ldh == {name:"刘德华",age:18,sex:"男",sing:f}
//3.利用构造函数创建对象的过程也称为对象的实例化
new关键字执行过程
//new关键字执行过程
//1. new 构造函数可以在内存中创建了一个空的对象
//2. this 就会指向刚才创建的空对象
//3. 执行构造函数里面的代码,给这个空对象添加属性和方法
//4. 返回这个对象(所以构造函数里面不需要return)
function Star(uname,age,sex){
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function (song) {
console.log(song);
}
}
var ldh = new Star('刘德华',18,'男'); //调用函数返回的是一个对象
console.log(ldh); // ldh == {name:"刘德华",age:18,sex:"男",sing:f}
遍历对象
//遍历对象
var obj = {
uname:'张三',
age :18,
sex:'男',
sayHi:functon(){
console.log('hello');
}
}
// for in 遍历我们的对象
// for(变量 in 对象){
//}
for(var k in obj){
console.log(k); // 打印:uname age sex 如果输出的是变量,得到的是属性名
console.log(obj[k]);//得到的是属性值 打印:{name:"张三",age:18,sex:"男",sayHi:hello}
}
//k是变量,不加引号
//for in 里面的变量,常用k或key命名
总结
JS内置对象
内置对象
JS对象分为三种:自定义对象,内置对象,浏览器对象
前两者是JS基础内容,属于ECMAScript;浏览器对象是JS独有的,在JS API中出现
内置对象是JS语言自带的一些对象,这些对象供开发者使用,并提供了一些常用或是最基本而必要的功能(属性和方法)
—— 直接封装好的一些代码,像是安装好的手机,不需要直到手机内部构造,直接可以使用
JS提供了多个内置对象:Math,Array,String等
查阅文档
内置对象很多,方法更多,很难一下子都记住。可以了解未知的内置对象使用方法。
MDN
学习一个内置对象的使用,只需要学会常用的方法使用即可,可以通过文档学习,通过MDN/W3C来查询。
Mozilla开发者网络(MDN)提供了有关开放网络技术(Open Web)的信息,包括HTML,CSS和万维网及HTML5应用的API。
MDN:https://developer.mozilla.org/zh-CN/
MDN(JS):https://developer.mozilla.org/en-US/docs/Web/JavaScript
学习对象中的方法
Math对象
Math对象是一个内置对象,它具有数学常数和函数的属性方法,跟数学有关的运算(求绝对值,取整,最大值等)都可以使用Math中的成员,它不是一个函数对象。
与其他全局对象不同的是,Math不是一个构造函数(构造器),Math的所有属性和方法都是静态的。
/Math数学对象 不是一个构造函数,所以我们不需要用new来调用,而是直接使用里面的属性和方法即可
console.log(Math.PI); //属性:圆周率
console.log(Math.max(1,2,3)); //3
console.log(Math.max(2,44,'张三')); //NaN ,其中含有字符串,则返回NaN;如果没有参数,则返回-INfinity,负的无穷大
案例:
//利用对象封装自己的数学对象,里面有PI圆周率 最大值和最小值
var myMath = {
PI :3.141592653;
max:function(){
var max = argument[0];
for(var i = 1;i < arguments.length;i++){
if(arguments[i] > max){
max = arguments[i];
}
}
return max;
},
min:function(){
var min = argument[0];
for(var i = 1;i < arguments.length;i++){
if(arguments[i] < min){
min = arguments[i];
}
}
return min;
}
}
console.log(myMath.PI); //3.141592653
console.log(myMath.max(1,2,3));//3
console.log(myMath.min(4,5,6));//4
Math方法
Math.PI( ) | 圆周率 |
---|---|
Math.floor() | 向下取整 |
Math.ceil() | 向上取整 |
Math.round() | 四舍五入,就近取整(如果是-3.5,结果为 -3) |
Math.abs() | 绝对值 |
Math.max()/Math.min() | 求最大和最小值 |
//绝对值
console.log(Math.abs(1));// 1
console.log(Math.abs(-1));// 1
console.log(Math.abs('-1'));// 隐式转换,把字符串型-1转化为数字型
console.log(Math.abs('张三'));// NaN
//取整方法
//Math.floor() 地板 向下取整 往小了取
console.log(Math.floor(1.1));// 1
console.log(Math.floor(1.9));// 1
//Math.ceil() 天花板 向上取整 往大了取
console.log(Math.ceil(1.1));// 2
console.log(Math.ceil(1.9));// 2
//Math.round() 四舍五入 其他数字都是四舍五入 但.5特殊,往大取值
console.log(Math.ceil(1.1));// 1
console.log(Math.ceil(1.9));// 2
console.log(Math.ceil(-1.1));// -1
console.log(Math.ceil(-1.5));// -1
随机数方法 random( )
//1.Math对象随机数方法 random()返回一个随机数的小数 0 <= x < 1
//2.这个方法里面不跟参数
//3.代码验证
console.log(Math.random());
//4.得到两个数之间的随机整数 并且 包含这2个整数
//Math.floor(Math.random()*(max - min + 1)) + min; //核心语句要背下来
function getRandom(min,max){
return Math.floor(Math.random()*(max - min + 1)) + min;
}
console.log(getRandom(1,10));
//5.随机点名
var arr = ['张三','李四','王二麻子'];
console.log(arr[getRandom(0,arr.length-1]);
</script>
案例:
//猜数字
//1.随机生成一个1~10之间的整数,用到Math.random()方法
//2.直到正确才停止,要一直循环
//3.while循环更简单
//4.核心算法:使用 if else if 多分枝语句来判断大于,小于,等于。
function getRandom(min,max){
return Math.floor(Math.random()*(max-min+1))+ min;
}
var random = getRandom(1,10);
while (true) { //死循环
// statement
var num = prompt('猜数字');
if (num > random()) {
alert("猜大了");
}else if{
alert("猜小了");
}else{
alert("猜对了");
break;//退出整个循环结束程序
}
}
Date日期对象
Date概述
Date实例是用来处理日期和时间
Date对象和Math对象不一样,它是一个构造函数,需要实例化后才能使用,只能通过Date构造函数来实例化日期对象。
//Date()日期对象是一个构造函数,不许要使用new来调用
var arr = new Array(); //创建一个数组对象
var obj = new Object();//创建了一个对象实例
Date( )方法的使用
获取当前时间必须实例化
//1.使用Date
var date = new Date(); //如果没有输入任何参数,则Date的构造器会依照系统设置的当前时间来创建一个Date对象
console.log(date);
Date( )构造函数的参数
如果括号里有时间,就返回参数里面的时间。
例如日期更是字符串为’2019-5-1’,可以写成newDate(‘2019-5-1’)或new Date(‘2019/5/1’)
//2.参数常用的写法:数字型2019,10,01或者是字符串型'2019-10-01 8:8:8'
var date1 = new Date(2019,10,1);
console.log(date1); // Fri Nov 01 2019 00:00:00 GMT+0800 (中国标准时间)返回的是11月,不是10月
var date2 = new Date('2019-10-1 8:8:8');
console.log(date2); //Tue Oct 01 2019 08:08:08 GMT+0800 (中国标准时间)
日期格式化
需要2019-10-1 8:8:8格式的日期,怎么做到?
要获取日期指定的部分,需要手动得到这种格式。
方法名 | 说明 | 代码 |
---|---|---|
getFullYear() | 获取当年 | dObj.getFullYear() |
getMonth() | 获取当月(0-11) | dObj.getMonth() |
getDate() | 获取当天日期 | dObj.getDate() |
getDay() | 获取星期几(周日0-周六6) | dObj.getDay() |
getHours() | 获取当前小时 | dObj.getHours() |
getMinutes() | 获取当前分钟 | dObj.getMinutes() |
getSeconds() | 获取当前秒钟 | dObj.getSeconds() |
//格式化日期 年月日
var date3 = new Date();
console.log(date3.getFullYear()); //返回当前日期的年 2019
console.log(date3.getMonth() + 1); //月份 返回的月份小1个月 记得月份+1
console.log(date3.getDate()); // 返回的是几号
console.log(date3.getDay()); //3 周一返回的是1
// 返回 2019 年 5 月 1 日 周三
var year = date3.getFullYear();
var month = date3.getMonth() + 1;
var dates = date3.getDate();
var arr = ['周日','周一','周二','周三','周四','周五','周六'];
var day = date3.getDay();
console.log('今天:'+year+'年'+month+'月'+dates+'日'+arr[day]);
console.log(date3.getDate());
console.log(date3.getDay());
//格式化日期 时分秒
console.log(date3.getHours()); //时
console.log(date3.getMinutes()); //分
console.log(date3.getSeconds()); //秒
//要求封装一个函数返回当前的时分秒 格式08:08:08
function getTime(){
var time = new Date();
var h = time.getHours();
h = h < 10 ? '0' + h : h;
var m = time.getMinutes();
m = m < 10 ? '0' + m : m;
var s = time.getSeconds();
s = s < 10 ? '0' + s : s;
return h + ':' + m + ':' + s;
}
console.log(getTime());//15:15:48
获得Date总的毫秒数
//获得Date总的毫秒数(时间戳),不是当前时间的毫秒数,而是距离1970年1月1日过来多少毫秒数
//1.通过valueOf() getTime()
var date = new Date();
console.log(date.valueOf()); //当前时间距离1970.1.1的总毫秒数
console.log(date.getTime()); //同上
//2.简单的写法(最常用的写法)
var date1 = +new Date(); //+new Date() 返回的是总毫秒数
console.log(date1);
//H5新增方法 获取总的毫秒数
console.log(Date.now());
案例:倒计时
核心算法:输入时间减去现在的时间就是剩余的时间,即倒计时,但是不能拿着时分秒相减,比如05分减去25分,结果会是负数的。
用时间戳来做,用户输入时间总的毫秒数减去现在时间总的毫秒数,得到的就是剩余时间的毫秒数。
把剩余时间总的毫秒数转换为天,时,分,秒。
转化公式如下:
d = parseInt(总秒数/60/60/24); //计算天数
h = parseInt(总秒数/60/60%24); //计算小时
m = parseInt(总秒数/60%60); //计算分数
s = parseInt(总秒数%60); //计算当前秒数
function conutDown(time){
var nowTime = +new Date(); //返回的是当前时间总的毫秒数
var inputTime = +new Date(time); //返回的是用户输入时间总的毫秒数
var times = (inputTime - nowTime)/1000;
//time是剩余时间的总秒数
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;
}
console.log(conutDown('2019-5-1 18:00:00'));
数组对象
检测是否为数组
//检测是否为数组
//instanceof 运算符,可以检测是否为数组
var arr = [];
var obj = {};
console.log(arr instanceof new Array());//true
console.log(obj instanceof new Array());//false
// Array.isArray(参数);H5新增的方法 ie9以上支持
console.log(Array.isArray(arr));
console.log(Array.isArray(obj));
添加删除数组方法
方法名 | 说明 | 返回值 |
---|---|---|
push(参数1…) | 末尾添加一个或多个元素,注意修改原数组 | 数组及新的长度 |
pop() | 删除数组的最后一个元素,把数组长度减1无参数,修改原数组 | 返回它删除的元素的值 |
unshift(参数1…) | 向数组的开头添加一个或更多元素,注意修改原数组 | 数组及新的长度 |
shift() | 删除数组的第一个元素,数组长度减1无参数,修改原数组 | 数组及第一个元素的值 |
//添加删除数组元素
//1.push() 在数组的末尾 添加一个或多个元素
var arr = [1,2,3];
//arr.push(4,'张三');
console.log(arr.push(4,'张三')); //5
console.log(arr);//[1,2,3,张三]
//push是可以给数组追加新的元素
//push()参数直接写 数组元素就可以了
//push完毕后,返回的结果新数组的长度
//原数组也会发生变化
//2.unshift 在数组的开头,添加一个或多个数组元素
console.log(arr.unshift('red','orange'));//6
console.log(arr);//['red','orange',1,2,3,'张三']
//unshift是可以给数组前面追加新的元素
//unshift()参数直接写数组元素就可以了
//unshift完毕后,返回的结果是新数组的长度
//原数组也会发生变化
//3.pop()可以删除数组的最后一个元素
console.log(arr.pop()); //张三
console.log(arr); //['red','orange',1,2,3]
//pop是可以删除数组的最后一个元素,记住一次只能删除一个元素
//pop()没有参数
//pop完毕之后,返回的结果是删除的那个元素
//原数组也会发生变化
//4.shift() 它可以删除数组的第一个元素
console.log(arr.shift()); //red
console.log(arr);//[orange',1,2,3]
//shift是可以删除数组的第一个元素,记住一次只能删除一个元素
//shift()没有参数
//shift完毕之后,返回的结果是删除的那个元素
//原数组也会发生变化
筛选数组
//有一个包含工资的数组[1500,2000,2100,1800],要求把数组中工资超过2000的删除,剩余的放到新数组里面
var arr = [1500,2000,2100,1800];
var newArr = [];
for(var i = 0;i < arr.length;i++){
if (arr[i] < 2000) {
//newArr[newArr.lenght] = arr[i];
newArr.push(arr[i]);
}
}
console.log(newArr);//[1500,1800]
数组排序
方法名 | 说明 | 是否修改原数组 |
---|---|---|
reverse() | 颠倒数组中元素的顺序,无参数 | 该方法会改变原来的数组,返回新的数组 |
sort() | 对数组的元素进行排列 | 该方法会改变原来的数组 ,返回新数组 |
//数组排序
//1.翻转数组
var arr = ['orange','yellow','red'];
arr.reverse();
console.log(arr);
//2.数组排序(冒泡排序)
var arr1 = [1,2,3,4];
arr1.sort(function(a,b){ //要记住
// return a - b; //按照增序的顺序排列
return b - a; //按照降序的顺序排列
});
console.log(arr1);//[4,3,2,1]
数组索引方法
方法名 | 说明 | 返回值 |
---|---|---|
indexOf( ) | 数组中查找给定元素的第一个索引 | 如果存在返回索引号,如果不存在,则返回-1 |
lastIndexOf() | 在数组中最后一个的索引 | 如果存在返回索引号,如果不存在,则返回-1 |
//返回数组元素索引号方法 indexOf(数组元素) 作用是返回该数组元素的索引号 从前面开始查找
//它只返回第一个满足条件的索引号
//它如果在该数组里面找不到元素,则返回的是-1
var arr = ['orange','yellow','red'];
console.log(arr.indexOf('red'));//2
//返回数组元素索引号方法 lastIndexOf(数组元素) 作用就是返回该数组元素的索引号 从后面开始查找
console.log(arr.lastIndexOf('orange')); //0
案例:数组去重
//数组去重['c','a','b','f','e','c','g','h','g'] 去除数组中重复的元素
//目标:把旧数组中不重复的元素选取出来放到新数组里,重复的元素只保留一个,放到新数组去重
//核心算法:遍历旧数组,然后拿着旧数组元素去查询新数组,如果该元素只在新数组里面没有出现过,就添加,否则不添加
//怎么知道该元素没有存在?利用新数组.indexOf(数组元素),如果返回时-1就说明新数组里面没有改元素
//封装一个去重的函数 独一无二的
function unique(arr){
var newArr = [];
for(var i = 0;i < arr.length;i--){
newArr.push(arr[i]);
}
}
return newArr;
var demo = unique(['c','a','b','f','e','c','g','h','g']);
console.log(demo); //'c','a','b','f','e','g','h'
数组转化为字符串
方法名 | 说明 | 返回值 |
---|---|---|
toString( ) | 把数字转换成字符串,逗号分割一项 | 返回一个字符串 |
join( ‘分隔符’) | 方法用于把数组中所有元素转化成一个字符串 | 返回一个字符串 |
//数组转换成字符串
//1.toString()将数组转换为字符串
var arr = [1,2,3];
console.log(arr.toString());//1,2,3
//2.join(分隔符)
var arr1 = ['red','orange','blue'];
console.log(arr1.join()); //red,orange,blue
console.log(arr1.join('-'));//red-orange-blue
console.log(arr1.join('&'));//red-orange-blue
方法名 | 说明 | 返回值 |
---|---|---|
concat() | 连接两个或多个数组,不影响原数组 | 返回一个新的数组 |
slice() | 数组截取slice(begin,end) | 返回被劫持项目的新数组 |
splice() | 数组删除splice(第几个开始,要删除个数) | 反会被删除项目的新数组,注意这个会影响原数组 |
字符串对象
基本包装类型
为了方便操作基本数据类型,JS还提供了三个特殊的引用类型:String,Number,Boolean。
基本包装类型是指把简单数据类型包装成复杂数据类型,这样基本数据类型就有了属性和方法。
//基本包装类型
var str = "Tom";
console.log(str.length);//3
//对象才有属性和方法 复杂数据类型才有属性和方法
//简单数据类型为什么会有length属性?
//因为js会把基本数据类型包装成复杂数据类型
//基本包装类型:将简单数据类型包装成为复杂数据类型
//1.把简单数据类型包装为复杂数据类型
var temp = new String('Tom');
//2.把临时变量的值给str
str = temp;
//3.销毁临时变量
temp = null;
字符串的不可变
不可变是指里面的值不可变,虽然看上去内容改变了,但其实是str指向发生变化,内存中新开辟了一个内存空间。
var str = 'orange';
console.log(str); //orange
//当重新给str赋值时,变量'orange'不会被修改,依然在内存中
//重新给字符串赋值,会重新在内存中开辟空间,这个特点是字符串的不可变
var str = 'red';
console.log(str) //red
//因为字符串的不可变所以不要大量的拼接字符,会有效率问题
var str = '';
for(var i = 1;i <= 100;i++){
str += i;
}
console.log(str);
根据字符返回位置
字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串。
方法名 | 说明 |
---|---|
indexOf() | 返回指定内容在元字符串中的位置,如果找不到就返回-1,开始的位置是index索引号 |
lastIndexOf() | 从后往前找,只找第一个匹配的 |
//字符串对象
//根据字符返回位置 str.indexOf('要查找的字符',[起始的位置]);
var str = '长莫长于博谋';
console.log(str.indexOf('长')); //0
console.log(str.indexOf('长',1)); //索引是1的位置开始往后查找 2
案例:
//查找字符串"abcoefoxyozzopp"中所有o出现的位置以及次数
//核心算法:先查找第一个o出现的位置
//只要indexOf返回的结果不是-1,就能继续往后查找
//因为indexOf只能查找到第一个,所有后面的查找,一定是当前索引加1,从而继续查找
var str = "abcoefoxyozzopp";
var index = str.indexOf('o');
var num = 0;//次数
while (index !== -1) {
// statement
console.log(index);
num++;
index = str.indexOf('o',index + 1);
}
console.log('次数'+num);//4
根据位置返回字符(重点)
方法名 | 说明 | 使用 |
---|---|---|
charAt(index) | 返回指定位置的字符(index字符串的索引号) | str.charAt(0) |
charCodeAt(index) | 获取指定位置处字符的ASCI码(index索引号) | str.charCodeAt(0) |
str[index] | 获取指定位置处字符 | H5,IE8支持,和charAt()等效果 |
//根据位置返回字符
//1.charAt(index) 根据位置返回字符
var str ='andy';
console.log(str.charAt(3));
//遍历所有字符
for(var i = 0;i <str.length;i++){
console.log(str.charAt(i));
}
//2.charCodeAt(index) 返回相应索引号ASCII值
//目的:判断用户按下了那个键
console.log(str.charCodeAt(0));//97
//3.str[index] H5新增的
console.log(str[0]); //a
案例:
//判断一个字符串"abcoefoxyozzopp"中出现次数最多的字符,并统计其次数
//o.a = 1
//o.b = 1
//o.c = 1
//o.o = 4
//核心算法:利用charAt() 遍历这个字符串
//把每个字符都储存给对象,如果对象没有该属性,就为 1 ,如果存在就+1
//遍历对象:得到最大值和该字符
var str = "abcoefoxyozzopp";
var o = {};
for(var i = 0;i < str.length;i++){
var chars = str.charAt(i); //chars 是字符串的每一个字符
if(o[chars]){ //o[chars]得到的是属性值
o[chars]++;
}else{
o[chars] = 1;
}
}
//2.遍历对象
var max = 0;
var ch = '';
for(var k in o){
//k得到的是属性名
//o[k]得到的是属性值
if(o[k]>max){
max = o[k];
ch = k;
}
}
console.log(max);
console.log('最多字符'+ ch);
字符串操作方法(重点)
方法名 | 说明 |
---|---|
concat(str1,str2) | concat()方法用于连接两个或多个字符串,拼接字符串,等效于+,+更常用 |
substr(start.length) | 从start位置开始(索引号),length取的个数 |
slice(start,end) | 从start位置开始,截取到end位置,end取不到(两者都是索引号) |
substring(start,end) | 从start位置开始,截取到end位置,end取不到,基本和slice相同,但是不接受负值 |
toUpperCase() | 转换大写 |
toLowerCase() | 转换小写 |
//字符串操作方法
//1.concat(str1,str2)
var str = 'andy';
console.log(str.concat('red'));
//2.substr('截取起始位置','截取几个字符');
var str1 = '改革春风吹满地';
console.log(str1.substr(2,2)); //第一个2,索引号的2,从第几个开始;第二个2,取几个字符
//3.替换字符串replace('被替换字符','替换为字符') 他只会替换第一个字符
var str = 'andyandy';
console.log(str.replace('a','b'));
//把字符串"abcoefoxyozzopp"里面所有的'o'替换为*
var str1 = "abcoefoxyozzopp";
while(str1.indexOf('o')!== -1){
str1 = str1.replace('o','*');
}
console.log(str1);
//4.字符转换为数组 split('') 数组转换为字符串join()
var str2 = 'red,pule,black';
console.log(str2.split(','));
var str3 = 'red&pule&black';
console.log(str3.split('&'));
简单数据类型和复杂数据类型
简单类型又称基本数据类型或者值类型,复杂类型又叫做引用类型。
值类型:简单数据类型/基本数据类型,在储存时变量存储的是值本身,因此称为值类型。
String,number,boolean,undefine,null
//简单数据类型 null 返回的是一个空对象 object
var time = null;
console.log(typeof time);
//如果有变量打算以后存储为对象,没想好放什么,这时候就给null
引用类型:复杂数据类型,在存储时变量存储的仅仅是地址(引用),称之为引用类型,通过new关键字创建的对象(系统对象,自定义对象),如Object,Array,Date等
堆栈空间
堆栈空间分配区别:
栈(操作系统):由操作系统自动分配释放存放函数的参数值,局部变量的值等,操作方法类似于数据结构中的栈。
简单数据类型存放到栈里面,里面直接开辟一个空间存放的是值。
堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
复杂数据类型存放到堆里面,首先存放地址,然后这个地址指向堆里面的数据。真正的对象实例存放在堆空间中。
注意:JS中并没有堆栈的概念,但两者在内存中互不干扰。
简单类型传参
function fn(a){
a++;
console.log(a);
}
var x = 10;
fn(x); //11
console.log(x); //10
复杂类型传参
function Person(name){
this.name = name;
}
function f1(x){ //x = p
console.log(x.name); //刘德华
x.name = "张学友";
console.log(x.name);//张学友
}
var p = new Person("刘德华");
console.log(p.name); //刘德华
f1(p);
console.log(p.name);//张学友