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) 是一种轻量级的数据交换格式。 易于人阅读和编写。

  1. JSON 数据的书写格式是:名称/值对。
  2. 里面的属性和值都要用 双引号 括起来
     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]

你可能感兴趣的:(JavaScript 基础三)