JavaScript 基础四
遍历对象的属性
for...in 语句用于对数组或者对象的属性进行循环操作。
for (变量 in 对象名字) {
在此执行代码
}
- 这个变量是自定义 符合命名规范 但是一般我们 都写为 k 或则 key
- 后面的是对象 可以 数组 因为 数组也属于对象
1) for in 遍历 对象
var obj = {
name: 'andy',
age: 18,
sex: '男'
}
console.log(obj.length); // undefined
for (var k in obj) {
console.log(k); // 这里的k 是属性名
console.log(obj[k]); // 这里的 obj[k] 是属性值
}
- 再对象里面, 这里的k 是 属性名
遍历 JSON格式
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。
- JSON 数据的书写格式是:名称/值对。
- 里面的属性和值都要用 双引号 括起来
var json = {
"id": "1",
"name": "andy",
"age": "18",
"tel": "110120"
}
for (var k in json) {
console.log(k); // 这里的k 是属性名
console.log(obj[k]); // 这里的 obj[k] 是属性值
}
简单类型和复杂类型
简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型
值类型:简单数据类型/基本数据类型,在存储时,变量中存储的是值本身,因此叫做值类型。
引用类型:复杂数据类型,在存储是,变量中存储的仅仅是地址(引用),因此叫做引用数据类型。
堆 和 栈
堆栈空间分配区别:
1、栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈;
2、堆(操作系统): 存储复杂类型(对象),一般由程序员分配释放, 若程序员不释放,由垃圾回收机制回收。
值类型内存分配
值类型(简单数据类型): string ,number,boolean,undefined,null
值类型变量 的 数据 直接存放在变量(栈空间)中
var n1 = 10;
var n2 = n1;
n1 = 20;
n1 结果为 20 n2 的值 还是 10
引用类型内存分配
引用类型(复杂数据类型):通过 new 关键字创建的对象(系统对象、自定义对象)Object Array Date等
引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中。
执行代码时,new 的对象实例 被创建在堆空间中,堆地址通过 = 号 赋值到变量 usrObj 的栈空间中。
我们通过变量 usrObj 访问 Object对象实例 里的内容时,实际是通过 栈空间里存放的堆地址来找到对象实例,再调用对象实例里的成员。
function Person(name, age) {
this.name = name;
this.age = age;
}
var p1 = new Person('andy', 55);
var p2 = p1;
p1.name = 'red';
console.log(p2.name);
值类型传参
思考以下代码结果:
function fn(a) {
a++;
console.log(a);
}
var x = 10;
fn(x);
console.log(x);
- 结论:函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值 复制 了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
引用类型传参
// 复杂数据类型(引用类型)传参
// 下面代码输出的结果?
function Person(name) {
this.name = name;
}
function f1(x) { // x = p
console.log(x.name); // 2. 这个输出什么 ? 刘德华
x.name = "张学友";
console.log(x.name); // 3. 这个输出什么 ? 张学友
}
var p = new Person("刘德华");
console.log(p.name); // 1. 这个输出什么 ? 刘德华
f1(p);
console.log(p.name); // 4.这个输出什么 ? 张学友
结论:函数的形参也可以看做是一个变量,当我们把 引用类型变量 传给 形参时,其实是把 变量在栈空间里保存的 堆地址 复制给了 形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。
Math对象
Math对象不是构造函数,它具有数学常数和函数的属性和方法。
跟数学相关的运算来找Math中的成员(求绝对值,取整)
Math
注意以下都是方法 所以 必须带括号
演示:Math.PI、Math.random()、Math.floor()/Math.ceil()、Math.round()、Math.abs()、Math.max()
Math.PI// 圆周率
Math.floor() // 向下取整
Math.ceil() // 向上取整
Math.round()// 四舍五入版 就近取整 注意 -3.5 结果是 -3
Math.abs()// 绝对值
Math.max()/Math.min() // 求最大和最小值
Math.sin()/Math.cos() // 正弦/余弦
Math.power()/Math.sqrt() // 求指数次幂/求平方根
Math.random 生成随机数
随机返回一个小数 , 取值范围 是 范围[0,1) 左闭右开 0 <= x < 1
console.log(Math.random()); // 0.40645855054029756
Date对象
Date对象 和 Math 对象不一样,他是一个构造函数。 所以我们需要 实例化使用。
创建 Date 实例用来处理日期和时间。Date 对象基于1970年1月1日(世界标准时间)起的毫秒数。
为什么计算机起始时间从1970年开始
1)Date() 的使用
// 获取当前时间,
var now = new Date();
console.log(now);
Date构造函数的参数
// 括号里面时间 ,就返回 参数里面的时间
日期格式字符串 '2015-5-1' new Date('2015-5-1') 或者 new Date('2015/5/1')
总结:
- 如果Date()不写参数,就返回当前时间
- 如果Date()里面写参数,就返回 括号里面输入的时间
2)获取日期的毫秒形式
Date 对象基于1970年1月1日(世界标准时间)起的毫秒数。
日期格式化方法
我们想要 2018-8-8 8:8:8 格式怎么办?
获取日期指定部分
所以我们手动的得到这种格式。方法名 说明 代码___d = new Date() getFullYear() 获取当年 d.getFullYear() getMonth() 获取当月(0-11) d.getMonth() getDate() 获取当天日期 d.getDate() getDay() 获取星期几 (周日0 到周六6) d.getDay() getHours() 获取当前小时 d.getHours() getMinutes() 获取当前分钟 d.getMinutes()
| getSeconds() | 获取当前秒钟 | d.getSeconds() |
- 注意 月份 和星期 取值范围是从 0开始的。
案例
- 2018年5月29日 星期二 请写出这个格式
function getMyDate() {
var arr = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var date = new Date();
// 2018年5月29日 星期二
var str = date.getFullYear() + '年' + (date.getMonth() + 1) + '月' + date.getDate() + '日 ' + arr[date.getDay()];
return str;
}
console.log(getMyDate());
写一个函数,格式化日期对象,HH:mm:ss 的形式 比如 00:10:45
function getTimer() {
var date = new Date();
// var str = date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
var h = date.getHours();
var m = date.getMinutes();
var s = date.getMinutes();
// if(h < 0) {
// h = '0' + h;
// }
h = h < 10 ? '0' + h : h
m = m < 10 ? '0' + m : m
s = s < 10 ? '0' + s : s
return h + ':' + m + ':' + s;
}
console.log(getTimer());
- 做一个倒计时效果
计算公式:
d = parseInt(总秒数/ 60/60 /24); // 计算天数
h = parseInt(总秒数/ 60/60 %24) // 计算小时
m = parseInt(总秒数 /60 %60 ); // 计算分数
s = parseInt(总秒数%60); // 计算当前秒数
function getCountTime(endTime) {
var d, h, m, s;
//1. 用用户输入的时间 减去 开始的时间就是 倒计时
//2. 但是要注意,我们得到是 毫秒数 然后 把这个毫秒数转换为 相应的 天数 时分秒 就好了
var countTime = parseInt((new Date(endTime) - new Date()) / 1000);
// console.log(countTime);
// 3. 把得到的毫秒数 转换 当前的天数 时分秒
console.log(countTime);
d = parseInt(countTime / 60 / 60 / 24); // 计算天数
h = parseInt(countTime / 60 / 60 % 24); // 计算小时
m = parseInt(countTime / 60 % 60); // 计算分数
s = parseInt(countTime % 60); // 计算当前秒数
return '还剩下' + d + '天' + h + '时' + m + '分' + s + '秒 ';
}
console.log(getCountTime('2020-5-30 17:30'));
Array对象
- 创建数组对象的两种方式
- 字面量方式
- new Array()
// 空数组
var arr = new Array();
// 数组长度为3 但是内容为空
var arr = new Array(3);
// 创建数组 [3,4,6]
var arr = new Array(3, 4, 6);
// 2. 使用字面量创建数组对象
var arr = [1, 2, 3];
// 获取数组中元素的个数
console.log(arr.length);
检测一个对象是否是数组
- instanceof instanceof 运算符 就是判断一个对象是否属于某种类型
- Array.isArray() HTML5中提供的方法,有兼容性问题
函数的参数,如果要求是一个数组的话,可以用这种方式来进行判断
var arr = [1, 23]; var obj = {}; console.log(arr instanceof Array); // true console.log(obj instanceof Array); // false console.log(Array.isArray(arr)); // true console.log(Array.isArray(obj)); // false
数组常用方法
演示:push()、shift()、unshift()、reverse()、sort()、splice()、indexOf() 等
1)添加删除数组元素方法
方法名 | 说明 | 返回值 |
---|---|---|
push(参数1....) | 末尾添加一个或多个元素 ,注意修改原数组, | 并返回新的长度 |
pop() | 删除 数组最后一个元素,把数组长度减 1 无参数、注意修改原数组, | 返回它删除的元素的值 |
unshift(参数1...) | 向数组的开头添加一个或更多元素,注意修改原数组, | 并返回新的长度 |
shift() | 把数组的第一个元素从其中删除,把数组长度减 1 无参数、注意修改原数组, | 并返回第一个元素的值 |
// push
var arr = ['pink', 'deeppink', 'hotpink'];
console.log(arr.push('lightpink')); // 返回数组长度 4
console.log(arr); // ['pink', 'deeppink', 'hotpink', 'linghtpink']
// pop
var arr = ['pink', 'deeppink', 'hotpink'];
console.log(arr.pop()); // 返回删除的那1个元素 'hotpink'
console.log(arr); // 返回删除的那1个元素 ["pink", "deeppink"]
// unshift
var arr = ['pink', 'deeppink', 'hotpink'];
console.log(arr.unshift('lightpink')); // 返回数组长度 4
console.log(arr); // ['linghtpink','pink', 'deeppink', 'hotpink']
// shift
var arr = ['pink', 'deeppink', 'hotpink'];
console.log(arr.shift()); // 返回删除的那1个元素 'pink'
console.log(arr); // 返回删除的那1个元素 ["deeppink", "hotpink"]
- 工资的数组[1500, 1200, 2000, 2100, 1800],把工资超过2000的删除
var arr = [1500, 1200, 2000, 2100, 1800];
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] < 2000) {
newArr.push(arr[i]);
}
}
console.log(newArr);
filter 方法
//数组的迭代方法
var arr1 = [2,2,4,3,5,6,75,32,35] //将大于10的数去除掉
var newArr1 = arr1.filter(function (ele,index,array){
console.log(ele);
if(ele > 10){
return false
}
return true;
})
console.log(newArr1);
2)数组排序方法
方法名 | 说明 | 是否修改原数组 |
---|---|---|
reverse() | 颠倒数组中元素的顺序,无参数 | 该方法会改变原来的数组 返回新数组 |
sort() | 对数组的元素进行排序 | 该方法会改变原来的数组 返回新数组 |
// reverse
var arr = ['red', 'andy'];
console.log(arr.reverse()); // 返回翻转之后的数组
console.log(arr); // 原先数组也被修改
sort 如果调用该方法时没有使用参数,按照字符编码的顺序进行排序。
var arr = [1, 64, 9, 6];
arr.sort(function(a, b) {
return b - a; // 降a序
// return a - b; 升序
});
console.log(arr);
3) 数组操作方法
方法名 | 说明 | 返回值 |
---|---|---|
concat() | 连接两个或多个数组 不影响原数组 | 返回一个新的数组 |
slice() | 数组截取slice(begin, end) | 返回被截取项目的新数组 |
splice() | 数组删除splice(第几个开始,要删除个数) | 返回被删除项目的新数组 注意,这个会影响原数组 |
var arr1 = [1, 2];
var arr2 = ['pink', 'red'];
var arr3 = ['andy', 18];
//返回连接之后的新数组
console.log(arr1.concat(arr2, arr3));
// arr.slice(begin, end) begin (包含自己) 和 end (不包含) 都是 索引号
var arr = ['red', 'green', 'blue', 'pink'];
console.log(arr.slice()); // 默认截取整个数组
console.log(arr.slice(0)); // 从第0个截取到最后
console.log(arr.slice(0, 3)); // 从第0个截取 截取 索引号是3的但是不包含3
// splice 删除
// 2. splice() 插入、删除或替换数组的元素
// (1) 删除某几个元素 数组.splice(起始位置, [删除的个数])
var arr = ['red', 'green', 'blue', 'pink'];
// 起始位置 从 0 开始计算 删除的个数 是删除几个的意思
arr.splice(2, 2); // 从索引号2的位置开始 删除 2个元素
console.log(arr);
var arr1 = ['red', 'green', 'blue', 'pink']; // 我们要把green 和blue 删掉
arr1.splice(1, 2); // 从索引号1的位置开始 删除 2个元素
console.log(arr1);
var arr2 = ['red', 'green', 'blue', 'pink']; // 我们要把green 和blue pink 删掉
arr2.splice(1); // 只写了一个起始位置不写删除的个数,默认从起始位置删除到数组的最后面
console.log(arr2);
// (2) 删除某几个元素 后的返回值 (跟我们前面学的 pop shift 返回的是被删除的元素)
var arr3 = ['red', 'green', 'blue', 'pink'];
console.log(arr3.splice(0, 2)); // 删除了 red green 返回值就是 red green
console.log(arr3); // 原数组剩下 blue pink
// (3) 插入或者 替换数组中的元素 数组.splice(起始位置, [删除的个数], [元素1, 元素2...])
var arr4 = ['red', 'green', 'blue', 'pink'];
// arr4.splice(0, 0, 'hotpink');
// arr4.splice(0, 0, 'hotpink', 'lightpink');
// 在 索引号2 的位置 前面 插入 某几个元素
arr4.splice(2, 0, 'hotpink', 'lightpink');
console.log(arr4);
// (4) 替换数组中的元素
var arr5 = ['red', 'green', 'blue', 'pink'];
// 我们把 pink 颜色替换为 skyblue (删掉 pink 替换为 skyblue)
arr5.splice(3, 1, 'skyblue');
console.log(arr5);
- 清空数组
// 方式1 推荐
arr = [];
// 方式2
arr.length = 0;
// 方式3
arr.splice(0, arr.length);
4) 数组位置方法
方法名 | 说明 | 返回值 |
---|---|---|
indexOf() | 数组中查找给定元素的第一个索引 | 如果存在返回索引号 如果不存在,则返回-1。 |
lastIndexOf() | 在数组中的最后一个的索引, | 如果存在返回索引号 如果不存在,则返回-1。 |
5) 数组转换为字符串
方法名 | 说明 | 返回值 |
---|---|---|
toString() | 把数组转换成字符串,逗号分隔每一项 | 返回一个字符串 |
join('分隔符') | 方法用于把数组中的所有元素转换为一个字符串。 | 返回一个字符串 |
var arr = [1, 2, 3, 4, 5];
console.log(arr.toString()); // 字符型 的 1,2,3,4,5
var arr = ['red', 'green', 'blue', 'pink'];
console.log(arr.join()); // 跟toString() 一样, 转换为字符串
console.log(arr.join('-')); //red-green-blue-pink
- 编写一个方法去掉一个数组的重复元素(重点案例必须掌握的)
// ['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b']; 取消重复的元素 数组去重 (for循环)
// 把旧数组里面 不重复的元素选取出来放到新数组中 重复的元素之保留一个 放到新数组中 数组去重
var arr = ['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'];
var newArr = []; // 新数组
for (var i = 0; i < arr.length; i++) { // 遍历的是旧数组
// 判断条件 我们去查询 --新数组-- 如果旧数组里面的一个元素在新数组里面没有出现过,我们就添加 否则不添加
if (newArr.indexOf(arr[i]) === -1) {
newArr.push(arr[i]);
}
}
console.log(newArr);
String对象
1) 基本包装类型(理解)
为了方便操作基本数据类型,JavaScript还提供了三个特殊的引用类型:String/Number/Boolean
基本包装类型就是 把简单数据类型包装成为复杂数据类型。 这样 基本数据类型就有了属性和方法
// 下面代码的问题?
var str = 'andy';
console.log(str.length);
// 按道理 基本数据类型 是 没有属性和方法的
// 对象才有属性和方法的
// 这个原因是因为, js 会把 基本数据类型包装为复杂数据类型
// 执行过程如下 生成临时变量 把简单类型包装为复杂数据类型
var temp = new String('andy');
// 赋值给 我们声明的 字符变量
str = temp;
// 销毁给临时变量
temp = null;
字符串的不可变
指的是里面的值不可变, 看上去可以改变内容,其实是地址变了,新开辟了一个内存空间。
var str = 'abc';
str = 'hello';
// 当重新给str赋值的时候,常量'abc'不会被修改,依然在内存中
// 重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变
// 由于字符串的不可变,在大量拼接字符串的时候会有效率问题
var str = '';
for (var i = 0; i < 100000; i++) {
str += i;
}
console.log(str); // 这个结果需要花费大量时间 来 显示 因为需要不断的开辟新的空间
- 创建字符串对象
var str = 'andy';
console.log(str); // 看不到常见的属性和方法
var str1 = new String('andy');
console.log(str1); // 可以看到常见的属性和方法
// 但是字符串经过基本包装类, 是可以使用 常见的属性和方法
字符串对象的常用方法
字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串
获取字符串位置方法(根据字符返回位置)
方法名 | 说明 |
---|---|
indexOf('要查找的字符', 开始的位置) | 返回指定内容在元字符串中的位置, 如果找不到就返回 -1,开始的位置是index 索引号 |
lastIndexOf() | 从后往前找,只找第一个匹配的 |
var str = 'my name is andy';
console.log(str.indexOf('n')); // 3
console.log(str.indexOf('l')); // -1
- "abcoefoxyozzopp"查找字符串中所有o出现的位置
// indexOf(要查找的元素, 查找的起始位置);
var str = 'abcoefoxyozzopp';
// 1. 先查找第一个o所在的位置
var index = str.indexOf('o');
// console.log(index);
// 2. 如果indexof 返回的结果 不是 -1 说明后面还有o 我们就继续查找 循环
while (index !== -1) {
console.log(index);
index = str.indexOf('o', index + 1);
}
根据位置获取字符
方法名 | 说明 | 使用 |
---|---|---|
charAt(index) | 返回指定位置的字符(index 字符串的索引号) | str.charAt(0) |
charCodeAt(index) | 获取指定位置处字符的ASCII码 (index索引号) | str.charCodeAt(0) |
str[index] | 获取指定位置处字符 | HTML5,IE8+支持 和charAt()等效 |
var str = 'andy';
console.log(str.charAt(0)); // a
// 可以遍历的方法 得到所有的字符串
for (var i = 0; i < str.length; i++) {
console.log(str[i]);
}
字符串操作方法
方法名 | 说明 |
---|---|
concat(str1,str2,str3...) | concat() 方法用于连接两个或多个字符串。拼接字符串,等效于+,+更常用 |
substr(start,length) | 从start位置开始(索引号) , length 取的个数 重点记住这个 |
slice(start, end) | 从start位置开始,截取到end位置,end取不到 (他们俩都是索引号) |
substring(start, end) | 从start位置开始,截取到end位置,end取不到 基本和slice 相同 但是不接受负值 |
var str1 = 'andy';
var str2 = 'red';
console.log(str1.concat(str2, '肖申克救赎')); // andyred肖申克救赎
var str = 'my name is andy';
console.log(str.substr(1)); // y name is andy 默认从第1个到最后
console.log(str.substr(0, 2)); // my 从第0个开始,取2个
console.log(str.substr(3, 7)); //name is 从第 3个索引号开始,取 7个
var str = 'my name is andy';
console.log(str.slice(1)); // y name is andy 默认从第1个到最后
console.log(str.slice(0, 2)); // my 从第0个开始,取到 第 1个(不包含2)
console.log(str.slice(3, 7)); // name
var str = 'my name is andy';
console.log(str.substring(1)); // y name is andy 默认从第1个到最后
console.log(str.substring(0, 2)); // my 从第0个开始,取到 第 1个(不包含2)
console.log(str.substring(3, 7)); // name
- 截取字符串"我爱中华人民共和国",中的"中华"
var s = "我爱中华人民共和国";
s = s.substr(2,2);
console.log(s);
replace() 替换
replace() 方法用于在字符串中用一些字符替换另一些字符
格式如下:
replace(被替换的字符串, 要替换为的字符串);
- 把字符串中所有的o替换成!
var s = 'abcoefoxyozzopp';
while (s.indexOf('o') !== -1) {
s = s.replace('o', '!');
}
console.log(s);
- 判断一个字符串中出现次数最多的字符,统计这个次数
var s = 'abcoefoxyozzopp';
var o = {};
for (var i = 0; i < s.length; i++) {
var item = s.charAt(i);
if (o[item]) {
o[item] ++;
}else{
o[item] = 1;
}
}
var max = 0;
var char ;
for(var key in o) {
if (max < o[key]) {
max = o[key];
char = key;
}
}
console.log(max);
console.log(char);
转换大小写
toUpperCase() //转换大写
toLowerCase() //转换小写
var str = 'ANDY';
console.log(str.toLowerCase()); // andy
var str = 'andy';
console.log(str.toUpperCase()); // ANDY
split 切割字符串为数组
注意,切割完毕之后,返回的是一个新数组
var str = 'a,b,c,d';
console.log(str.split(',')); //返回的是一个数组 [a, b, c, d]