**七、函数
在JS里面,可能会定义非常多的相同代码或者功能相似的代码,这些代码可能需要大量重复使用。
虽然 for 循环语句也能实现-些简单的重复操作,但是比较具有局限性,此时我们就可以使用JS中的函数。
函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。
7.1 函数使用
函数使用分为两步:声明函数和调用函数。
1)声明函数
1 | function 函数名() { |
(1) function 是声明函数的关键字,必须小写。
(2) 函数是做某件事情,函数名一般是动词 sayHi
(3) 函数不调用自己不执行
2) 调用函数
1 | 函数名(); |
调用函数的时候千万不要忘记加小括号。
3)函数的封装
函数的封装是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口
简单理解:封装类似于将电脑配件整合组装到机箱中(类似快递打包)
7.2 函数的参数
1)形参和实参
在声明函数时,可以在函数名称后面的小括号中添加一些参数,这些参数被称为形参,而在调用该函数时,同样也需要传递相应的参数,这些参数被称为实参。
参数 | 说明 |
---|---|
形参 | 形式上的参数函数定义的时候传递的参数当前并不知道是什么 |
实参 | 实际上的参数函数调用的时候传递的参数实参是传递给形参的 |
参数的作用:在函数内部某些值不能固定, 我们可以通过参数在调用函数时传递不同的值进去。
2) 函数形参实参个数匹配问题
如下函数
1 | function getSum(num1, num2) { |
1)如果实参的个数和形参的个数一致 则正常输出结果
1 | getSum(1, 2);//3 |
2)如果实参的个数多于形参的个数 会取到形参的个数
1 | getSum(1, 2, 3);//3 |
3)如果实参的个数小于形参的个数 ,多于的形参定义为undefined ,最终的结果就是 NaN。
1 | getSum(1); // NaN |
形参可以看做是不用声明的变量, num2 是一个变量但是没有接受值 , 结果就是undefined 。
我们尽量让实参的个数和形参相匹配
7.3 函数的返回值
1) return语句
有的时候,我们会希望函数将值返回给调用者,此时通过使用return语句就可以实现。
(1) 我们函数只是实现某种功能, 最终的结果需要返回给函数的调用者函数名() ,通过return 实现的。
(2) 只要函数遇到return 就把后面的结果, 返回给函数的调用者 , 函数名() = return后面的结果。
2) 函数返回值注意事项
1.return可以终止函数
1 | function getSum(num1, num2) { |
2.return 只能返回一个值
1 | function fn(num1, num2) { |
3.return任意两个数的加减乘数结果
1 | function getResult(num1, num2) { |
4.函数return
我们的函数如果有return 则返回的是 return 后面的值。如果函数没有return ,则返回undefined。
1 | function fun1() { |
7.4 arguments使用
当我们不确定有多少个参数传递的时候,可以用arguments来获取。
在JavaScript中, arguments实际上它是当前函数的一个内置对象。所有函数都内置了一个arguments对象, arguments对象中存储了传递的所有实参。只有函数才有 arguments对象。
function fn() {
console.log(arguments); // 里面存储了所有传递过来的实参 arguments = [1,2,3]
console.log(arguments.length);//3
console.log(arguments[2]);//3
}
fn(1, 2, 3);
1)伪数组
arguments展示形式是一个伪数组 ,因此可以遍历,伪数组并不是真正意义上的数组。
具有数组的 length 属性
按照索引的方式进行存储的
它没有真正数组的一些方法 pop() push() 等等
2)遍历arguments
按照数组的方式遍历arguments。
function fn() {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
fn(1, 2, 3,4);
7.5 函数的声明方式
1)命名声明函数
利用函数关键字自定义函数(命名函数)
1 | function fn() { |
2.函数表达式(匿名函数) 声明
var 变量名 = function() {};
1 | var fun = function(aru) { |
(1) fun是变量名, 不是函数名,
(2) 函数表达式声明方式跟声明变量差不多,只不过变量里面存的是值 ,而函数表达式里面存的是函数,
(3) 函数表达式也可以进行传递参数。
7.6 函数的内部属性
函数内部有两个特殊对象:arguments和this
**八、作用域
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
8.1 JS的作用域
js的作用域(es6)之前 : 全局作用域 和 局部作用域
全局作用域: 整个script标签 或者是一个单独的js文件
局部作用域(函数作用域) :在函数内部就是局部作用域 ,这个代码的名字只在函数内部起效果和作用。
8.2 变量的作用域
变量的作用域:根据作用域的不同我们变量分为 全局变量 和 局部变量。
1.全局变量: 在全局作用域下的变量 ,在全局下都可以使用,无论是在函数内部还是外部。
注意 :如果在函数内部, 没有声明直接赋值的变量也属于全局变量
2.局部作用域
局部变量是只能在函数内部使用。
1 | function fun(aru) { |
3.从执行效率来看全局变量和局部变量
- 全局变量:只有浏览器关闭的时候才会销毁,比较占内存资源。
- 局部变量:当我们程序执行完毕就会销毁, 比较节约内存资源
8.3 块级作用域
js的作用域包括:全局作用域 和 局部作用域 ,现阶段我们js没有块级作用域。
我们js 也是在 es6 的时候新增的块级作用域。
什么是块级作用域?
就像{} if {} for {}这种,变量只会在作用域中有用,比如下面这段java代码
1 | if(xx) { |
但是在JS中,不会有块级作用域
1 | if (3 < 5) { |
8.4 作用域链
只要是代码,就至少有一个作用域 。
如果函数中还有函数 ,那么在这个作用域中就又可以诞生一个作用域,根据在内部函数可以访问外部函数变量的这种机制 ,用链式查找决定哪些数据能被内部函数访问,就称作作用域链。
1 | // 作用域链 :就近原则 |
上面的console会输出20,从上面可以看出函数的使用需要先定义再使用,程序执行的顺序是从上到下依次执行可执行语句,就像上面首先执行 var num = 10; 接着就是 fn1();,然后进入函数的内部。
就近原则的案例
1 | function f1() { |

**九、预解析
JavaScript代码是由浏览器中的JavaScript解析器来执行的。
JavaScript 解析器在运行JavaScript代码的时候分为两步:
1)预解析
js 引擎会把 js 里面所有的 var 声明 和 function声明 提升到当前作用域的最前面。
2)代码执行
按照代码书写的顺序从上往下执行。
预解析分为变量预解析(变量提升) 和 函数预解析(函数提升)。
9.1 变量提升
就是把所有的变量声明(var)提升到当前的作用域最前面 ,但是不提升赋值操作。
当仅有下面一行代码的时候,控制台会报错
1 | console.log(num); |
如下代码,控制台不会报错,会显示num 是 undefined。
1 | console.log(num); // undefined |
上面就是变量提升的例子,上面的代码在js预解析之后相当于执行了以下代码,因此控制台输出时,变量是声明但未赋值,就是undefined。
1 | var num; |
变量声明的函数
如下代码,控制台报错,fun不是一个function
1 | fun(); |
这里也用到了变量提升,相当于执行了以下代码
1 | var fun; |
因此,函数调用必须写在函数表达式的下面
9.2 函数提升
就是把所有的函数声明提升到当前作用域的最前面 ,但是不调用函数。
下面代码函数调用写在函数表达式的下面,但是依然会正常输出。
1 | fn(); |
这里用到了函数提升的概念,相当于执行了以下代码
1 | function fn() { //把函数声明提到当前作用域的前面,但是不调用函数 |
十、对象
现实生活中:万物皆对象,对象是一个具体的事物,看得见摸得着的实物。
例如,一本书、一辆汽车、一个人可以是“对象”, 一个数据库、一张网页、 一个与远程服务器的连接也可以是“对象”。
什么是对象?
在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。对象是由属性和方法组成的。
属性:事物的特征,在对象中用属性来表示(常用名词)
方法:事物的行为,在对象中用方法来表示(常用动词)

为什么需要对象
保存一个值时,可以使用变量,当保存多个值( 一组值)时,可以使用数组。如果要保存一个人的完整信息呢 ?
1 | var infor = ['张三','男',124] |
显然使用数组语义化不清晰,我们可以凭借经验知道数组的前两个数据是姓名和性别,但是缺不清楚第三个数据是什么。js中的对象可以解决这一问题,对象通过属性可以清楚的知道,每个数据的含义。
变量和属性
相同点: 他们都是用来存储数据的
不同点:
变量是单独声明并赋值 ,使用的时候直接写变量名 ,他是单独存在。
属性是在对象里面的不需要声明的 ,使用的时候必须是 对象.属性。
函数和方法
相同点:都是实现某种功能 做某件事
不同点:
函数是单独声明,调用的时候通过函数名() ,它是单独存在的
方法是在对象里面 ,不需要声明,调用的时候通过 对象.方法()
10.1创建对象的三种方式
1- 字面量创建对象
对象字面量:就是花括号{}里面包含了表达这个具体事物(对象)的属性和方法。
{} 里面的属性或者方法我们采取键值对的形式 :键(属性名 ):值(属性值)。多个属性或者方法中间用逗号(,)隔开的,方法冒号后面跟的是一个匿名函数。
1 | // var obj = {}; // 创建了一个空的对象 |
调用属性
1)调用对象的属性,采取对象名.属性名
1 | console.log(obj.uname); |
2)调用属性还有一种方法 对象名[‘属性名’]
1 | console.log(obj['age']); |
调用方法
3)调用对象的方法 ,通过对象名.方法名()
1 | obj.sayHi();//千万别忘记添加小括号 |
2-new obiect创建对象
我们是利用 等号 = 赋值的方法去添加对象的属性和方法,每个属性和方法之间用分号(;)结束。Object()的第一个字母要大写。
1 | // 利用 new Object 创建对象 |
3-构造函数创建对象
为什么需要使用构造函数?
就是因我们前面两种创建对象的方式一次只能创建一个对象,每个对象里面很多的属性和方法是大量相同的 我们只能复制 。因此我们可以利用函数的方法 重复这些相同的代码 我们就把这个函数称为 构造函数。
构造函数就是把我们对象里面一些相同的属性和方法抽象出来封装到函数里面。
利用构造函数创建对象
1 | 构造函数的语法格式 |
案例-1:创建四大天王的对象
相同的属性: 名字 、年龄、 性别,相同的方法: 唱歌。
1)声明构造函数,构造函数的关键字首字母大写
1 | function Star(uname, age, sex) { |
2)通过New调用构造函数
1 | var ldh = new Star('刘德华', 18, '男'); // 调用函数返回的是一个对象 |
构造函数和对象
构造函数,如Stars() ,抽象了对象的公共部分,封装到了函数里面,它泛指某一 大类( class ),创建对象 ,如new Stars(), 特指某一个,通过new关键字创建对象的过程我们也称为对象实例化。
new调用构造函数的过程
new在执行时会做四件事情:
1.在内存中创建一个新的空对象。
2.让this指向这个新的对象。
3.执行构造函数里面的代码,给这个新对象添加属性和方法。
4.返回这个新对象(所以构造函数里面不需要return )。
遍历对象
使用 for in遍历对象的属性, 里面的变量 我们喜欢写 k 或者 key
for (变量 in 对象) {
}
比如下面这个例子
1 | var obj = { |
10.2 内置对象
JavaScript 中的对象分为3种:自定义对象、内置对象、浏览器对象。前面两种对象是JS基础内容,属于ECMAScript;第三个浏览器对象属于我们JS独有的,我们JS API讲解
内置对象就是指JS语言自带的一些对象,这些对象供开发者使用,并提供了一 些常用的或是最基本而必要的功能(属性和方法)。内置对象最大的优点就是帮助我们快速开发
JavaScript 提供了多个内置对象:Math、Date 、Array、 string等
怎么查阅文档
MDN
学习一个内置对象的使用,只要学会其常用成员的使用即可,我们可以通过查文档学习,可以通过MDN 、W3C来查询。Mozilla开发者网络( MDN )提供了有关开放网络技术( Open Web )的信息,包括HTML、CSS和万维网及HTMLS MFÁS APl.
MDN:https://developer.mozilla.org/zh-CN/
如何学习对象中的方法
1.查阅该方法的功能
2.查看里面参数的意义和类型
3.查看返回值的意义和类型
4.通过demo进行测试
1)Math对象
Math数学对象不是一个构造函数 ,所以我们不需要new 来调用 ,而是直接使用里面的属性和方法即可。隐式转换。
1 | console.log(Math.PI); // 一个属性 圆周率 |
Math对象不是构造函数,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用Math中的成员。
1.绝对值方法
1 | console.log(Math.abs(1)); // 1 |
2.三个取整方法
(1) Math.floor() 地板 向下取整 往最小了取值
1 | console.log(Math.floor(1.1)); // 1 |
(2) Math.ceil() ceil 天花板 向上取整 往最大了取值
1 | console.log(Math.ceil(1.1)); // 2 |
(3) Math.round() 四舍五入 。
其他数字都是四舍五入,但是 .5 特殊 它往大了取
1 | console.log(Math.round(1.1)); // 1 |
以最后一个-1.5为例,往大的取就是-1.
3.Math对象随机数方法
random() 返回一个随机的小数 0 =< x < 1,这个方法里面不跟参数
1 | console.log(Math.random()); |
案例—随机整数
我们想要得到两个数之间的随机整数 并且 包含这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));
案例—随机点名
将数据保存到数组中,可以利用随机数表示数组的下标
1 | var arr = ['张三', '张三丰', '张三疯子', '李四', '李思思', 'pink老师']; |
2)Date对象
Date() 日期对象是一个构造函数,必须实例化之后才能使用,通过new 来调用创建我们的日期对象。Date实例主要用来处理时间和日期。
获取当前时间
1.使用Date 如果没有参数 返回当前系统的当前时间
1 | var date = new Date(); |
2.参数常用的写法
数字型 2019, 10, 01 ;
字符串型 ‘2019-10-1 8:8:8’ 常用
1 | var date1 = new Date(2019, 10, 1); |
日期格式化(分别获取年月日时分秒)
我们想要2019-8-88:8:8 格式的日期,要怎么办?
需要获取日期指定的部分,所以我们要手动的得到这种格式。

案例—格式化日期 年月日
date.getMonth() :返回的月份比实际月份小1个月 。
date.getDay(): 周一返回的是 1 周六返回的是 6 但是 周日返回的是 0
var date = new Date();
console.log(date.getFullYear()); // 返回当前日期的年 2019
console.log(date.getMonth() + 1); // 返回的月份小1个月
console.log(date.getDate()); // 返回的是几号
console.log(date.getDay()); // 周一返回的是 1 周六返回的是 6 但是 周日返回的是 0
案例—格式化当前日期
预期输出:今天是:2020年5月19日 星期二
1 | var date = new Date(); |
案例—格式化日期——时分秒
要求封装一个函数返回当前的时分秒 格式 08:08:08
1 | function getTimer() { |
***获取日期的总的毫秒形式(时间戳)
Date对象是基于1970年1月1日(世界标准时间)起的毫秒数。我们经常利用总的毫秒数来计算时间,因为它更精确。获得Date总的毫秒数(时间戳) , 不是当前时间的毫秒数 而是距离1970年1月1号过了多少毫秒数。
1.通过 valueOf() getTime()
1 | var date = new Date(); |
2.简单的写法 (最常用的写法)
1 | var date1 = +new Date(); // +new Date() 返回的就是总的毫秒数 |
3.H5 新增的 获得总的毫秒数
1 | console.log(Date.now()); |
案例— 倒计时
①核心算法:输入的时间 - 现在的时间 = 剩余的时间,即倒计时,但是不能拿着时分秒相减,比如05分减去25分,结果会是负数的。
②用时间戳来做。用户输入时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的毫秒数。
③把剩余时间总的毫秒数转换为天、时、分、秒(时间戳转换为时分秒)
转换公式如下:
d = parselnt(总秒数/ 60/60/24); // 计算天数
h = parselnt(总秒数/ 60/60 %24) // 计算小时
m= parselnt(总秒数/60 %60); //计算分数
S = parselnt(总秒数%60);
计算当前秒数
1 | function countDown(time) { |
10.3 数组对象
1)数组对象的创建
创建数组对象的两种方式
字面量方式
var arr = [1, 2, 3];
console.log(arr[0]);
new Array()
1 | // var arr1 = new Array(); // 创建了一个空的数组 |
2)检测是否为数组
(1)instanceof 运算符 它可以用来检测是否为数组
var arr = [];
var obj = {};
console.log(arr instanceof Array);//true
console.log(obj instanceof Array);//false
(2) Array.isArray(参数); H5新增的方法 ie9以上版本支持
1 | console.log(Array.isArray(arr));//true |
3)添加 / 删除数组元素
splice方法的第二个参数设置为0,有在特定位置添加数组元素的意思,具体下文splice的介绍
方法名 | 说明 | 返回值 |
---|---|---|
push(参数1….) | 末尾添加一个或多个元素,注意修改原数组 | 并返回新的长度 |
pop() | 删除数组最后一个元素, 把数组长度减1无参数、修改原数组 | 返回它删除的元素的值 |
unshift(参数..) | 向数组的开头添加一个或更多元素,注意修改原数组 | 并返回新的长度 |
shift() | 删除数组的第一个元素, 数组长度减1无参数、修改原数组 | 并返回第一个元素的值 |
1.push() 在我们数组的末尾添加一个或者多个数组元素 , push 推
var arr = [1, 2, 3];
console.log(arr.push(4, 'pink'));//5
console.log(arr);//新的数组对象
- push 是可以给数组追加新的元素
- push() 参数直接写 数组元素就可以了
- push完毕之后,返回的结果是新数组的长度
- 原数组也会发生变化
2.unshift 在我们数组的开头 添加一个或者多个数组元素
1 | console.log(arr.unshift('red', 'purple')); |
unshift是可以给数组前面追加新的元素
unshift() 参数直接写 数组元素就可以了
unshift完毕 之后,返回的结果是 新数组的长度
原数组也会发生变化
3.pop() 它可以删除数组的最后一个元素
1 | console.log(arr.pop()); |
- pop是可以删除数组的最后一个元素,记住一次只能删除一个元素
- pop() 没有参数
- pop完毕之后,返回的结果是 删除的那个元 素
- 原数组也会发生变化
4.shift() 它可以删除数组的第一个元素
console.log(arr.shift());
console.log(arr);
- shift是可以删除数组的第一个元素 ,一次只能删除一个元素
- shift() 没有参数
- shift完毕之后,返回的结果是,删除的那个元素
- 原数组也会发生变化
4)数组排序
1.翻转数组,使用reverse直接实现数组翻转。
var arr = ['pink', 'red', 'blue'];
arr.reverse();
console.log(arr);
2.数组排序(冒泡排序)
sort() 方法对数组元素进行排序,当数组元素都仅有一位数时,返回正常排序结果。但是当数组元素有多位数时,排序结果发生错误。这时需要在sort()里面添加函数,如下
1 | var arr1 = [13, 4, 77, 1, 7]; |
5)数组索引
返回数组元素索引号方法
1.indexOf(数组元素) ,作用就是返回该数组元素的索引号, 从前面开始查找,它只返回第一个满足条件的索引号 ,它如果在该数组里面找不到元素,则返回的是 -1
var arr = ['red', 'green', 'blue', 'pink', 'blue'];
console.log(arr.indexOf('blue')); //2
2.lastIndexOf(数组元素) , 作用就是返回该数组元素的索引号 从后面开始查找
1 | var arr = ['red', 'green', 'blue', 'pink', 'blue']; |
案例—数组去重(重点案例)
有一个数组 [‘c’, ‘a’,、z’, a’, ‘x’, ‘a’, ‘x’, ‘c’, ‘b’] ,要求去除数组中重复的元素。
①目标:把旧数组里面不重复的元素选取出来放到新数组中,复的元素只保留一个,放到新数组中去重。
②核心算法:我们遍历旧数组,然后拿着I旧数组元素去查询新数组,如果该元素在新数组里面没有出现过,我们就添加,否则不添加。
③我们怎么知道该元素没有存在?
利用新数组.indexOf(数组元素)如果返回时-1就说明新数组里面没有该元素
1 | // 封装一个 去重的函数 unique 独一无二的 |
6)数组转化为字符串
1.toString() 将我们的数组转换为字符串
var arr = [1, 2, 3];
console.log(arr.toString()); // 1,2,3
2.join(分隔符) ,强大,可以设置元素之间的分隔符。
1 | var arr1 = ['green', 'blue', 'pink']; |
7)其他方法
方法名 | 说明 | 返回值 |
---|---|---|
concat() | 连接两个或多个数组,不影响原数组 | 返回一个新的数组 |
slice() | 数组截取slice(begin, end) | 返回被截取项目的新数组(也即是截取之后的数组) |
splice() | 数组删除splice(第几个开始,要删除个数) 返回被删除项目的新数组注意,这个会影响原数组 | slice()和splice(目的基本相同,建议同学们重点看下splice() |
splice()
splice()方法有)三种作用:删除元素/插入元素/替换元素
- 删除元素: 第二个参数传入你要删除几个元素(如果没有传,就删除后面所有的元素)
- 替换元素: 第二个参数, 表示我们要替换几个元素, 后面是用于替换前面的元素
- 插入元素: 第二个参数, 传入0, 并且后面跟上要插入的元素
1 | const letters= ['a', 'd', 'c', 'b']; |
10.4字符串对象
为了方便操作基本数据类型, JavaScript还提供了三个特殊的引用类型: String、Number和Boolean。
基本包装类型就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法。比如代码str只是一个字符串类型,怎么会有length属性?
var str = 'andy';
console.log(str.length);//5
按道理基本数据类型是没有属性和方法的,而对象才有属性和方法,但上面代码却可以执行,这是因为js会把基本数据类型包装为复杂数据类型,
其执行过程如下:
1 | // (1) 把简单数据类型包装为复杂数据类型 |
1)字符串的不可变性
字符串的不可变性指的是:里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。
1 | var str = 'abc' ; |
重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变,由于字符串的不可变,在大量拼接字符串的时候会有效率问题。
比如下面这个例子,控制台输出需要很长时间。
1 | var str = ''; |
2)根据字符返回位置
字符串所有的方法,都不会修改字符串本身(字符串是不可变的) ,操作完成会返回一个新的字符串。
方法名 | 说明 |
---|---|
indexOf(要查找的字符,开始的位置) | 返回指定内容在元字符串中的位置,如果找不到就返回-1,开始的位置是index索引号 |
lastIndexOf() | 从后往前找,只找第一个匹配的 |
1 | var str = '改革春风吹满地,春天来了'; |
案例:查找字符串”abcoefoxyozzopp”中所有o出现的位置以及次数
核心算法:先查找第一个o出现的位置。
然后只要indexOf 返回的结果不是 -1 ,就继续往后查找。
因为indexOf 只能查找到第一个,所以后面的查找,一定是当前索引加1,从而继续查找。
1 | var str = "oabcoefoxyozzopp"; |
**3)从字符串中获取单个字符
方法名 | 说明 | 使用 |
---|---|---|
charAt(index) | 返回指定位置的字符(index字符串的索引号) | str.charAt(0) |
charCodeAt(index) | 获取指定位置处字符的ASCII码(index索引号) | str.charCodeAt(0) |
str[index] | 获取指定位置的字符 | HTML5,IE8+支持和charAt()等效 |
charAt(index) 根据位置返回字符
var str = 'andy'; console.log(str.charAt(3)); // 遍历所有的字符 for (var i = 0; i < str.length; i++) { console.log(str.charAt(i)); }
charCodeAt(index)
返回相应索引号的字符ASCII值。目的: 判断用户按下了哪个键 ,每个按键都对应唯一的ASCII值。
1 | console.log(str.charCodeAt(0)); // 97 |
3. str[index] H5 新增的
1 | console.log(str[0]); // a |
判断对象 是否有该属性 对象[‘属性名’]
var o = {
age: 18
}
if (o['sex']) {
console.log('里面有该属性');
} else {
console.log('没有该属性');
}
案例-2:判断一个字符串 ‘abcoefoxyozzopp’ 中出现次数最多的字符,并统计其次数。
核心算法:利用 charAt(),遍历这个字符串,把每个字符都存储给对象, 如果对象没有该属性,就为1,如果存在了就 +1。
o.a = 1
o.b = 1
o.c = 1
o.o = 4
遍历对象,得到最大值和该字符。
1 | var str = 'abcoefoxyozzopp'; |
**4)字符串操作方法
方法名 | 说明 |
---|---|
concat(str1,str2,st3..) | concat()方法用于连接两个或多个字符串。拼接字符串,等效于+, +更常用。 |
substr(start,length) | 从start位置开始(索引号),length 取的个数重点记住这个 |
slice(start, end) | 从start位置开始,截取到end位置, end取不到(他们俩都是索引号) |
substring(start, end) | 从start位置开始,截取到end位置,end取不到,基本和slice 相同但是不接受负值 |
1.concat(‘字符串1’,’字符串2’….)
var str = 'andy';
console.log(str.concat('red'));
2.substr(‘截取的起始位置’, ‘截取几个字符’); 第二个参数可以省略
1 | var str1 = '改革春风吹满地'; |
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(‘分隔符’)
1 | // 前面我们学过 join 把数组转换为字符串 |
5.字符大小写转换
toUpperCase() 转换大写
toLowerCase() 转换小写
十一、简单类型与复杂类型
简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。
- 值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型string , number , boolean , undefined , null
- 简单数据类型 null 返回的是一个空的对象 object
- 如果有个变量我们以后打算存储为对象,暂时没想好放啥, 这个时候就给 null
1 | var timer = null; |
- 引用类型 :复杂数据类型,在存储时变量中存储的仅仅是地址(引用) , 因此叫做引用数据类型。通过new关键字创建的对象(系统对象、自定义对象) , 如Object、Array、 Date等
11.1 堆 栈空间分配区别:
1、栈(操作系统) :由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面
2、堆(操作系统) :存储复杂类型(对象) , -般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型存放到堆里面

注意: JavaScript中没有堆栈的概念,通过堆栈的方式,可以让大家更容易理解代码的一些执行方式,便于将来学习其他语言。
11.2 数据类型内存分配
简单数据类型是存放在栈里面, 里面直接开辟一个空间存放的是值。
复杂数据类型首先在栈里面存放地址(十六进制表示 ) ,然后这个地址指向堆里面的数据。

11.3 简单类型传参
函数的形参也可以看做是一个变量 ,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
1 | function fn(a) { |

11.4 复杂类型传参
函数的形参也可以看做是一个变量 ,当我们把引用类型变量传给形参时,实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。
1 | // 复杂数据类型传参 |
