Js高级程序设计第三版学习(五章)
第五章 引用类型
1.引用类型: 是一种数据结构,也可以被称之为类,但是在js中,引用类型并不具备类和接口等基础结构,,引用类型的值被称为对象
2.Object类型: js中大多数引用类型的值都是object类型的实例,Object类型 对于储存和传输数据而言,是非常理想的选择.
创建对象有两种方法: 在字面量方式创建对象中 最后一个属性结尾不要加逗号(,),会在低版本ie报错
// new 关键字创建对象
var obj = new Object();
obj.name = '你好';
// 对象字面量方式创建对象 (推荐) 可读性
var obj2 = {
name: '我不好',
age: 101
};
对象属性的访问方法:
var obj = new Object();
obj.name = '你好';
//可以用.的形式 或者[]形式
obj.name;
obj['name'];
//区别 Object的属性名 可以存在非数字或者非字母 而.的方式无法访问 [] 方式可以
// obj.nihao mingtian = '???' // 会报错
obj['nihao mingtian'] = 'lalal'
console.log(obj['nihao mingtian'] ); // lalal
3.Array类型: js中Array类型的每一项都可以存放任意类型的数据,而且数组的长度不是固定的,会自动增长.
创建数组同样有两种方法: 在字面量方式创建数组中 最后一个属性结尾不要加逗号(,),会在低版本ie会出现多出一项,值为undefined
//new 方式创建数组
var list = new Array();
//也可以省略new
var list2 = Array('red', 'black', 'blue', 'white');
//字面量方式创建 (推荐)
var list3 = [1, 2, 3, 4, 5, 6, 7];
数组的length并不是只读的,我们可以改变数组的长度,多出的项为undefined,少于的项被删除
- 检测数组 : instanceof 可以检测数组 但是如果网页存在多个框架 存在多个全局环境就可能会出现问题, 所以 es5 推出了 Array.isArray(list)检测到底是不是数组, ie9+支持
- 转换方法 : toString(), valueOf(),toLocaleString(),join(), 如果数组中 有一项为null or undefined 就用空字符串表示,其中join()方法穿参数就用 参数分割数组,不传就用默认,表示
- 栈方法 (后进先出): push() 推入, 在数组末尾添加一项 pop() 弹出,把末尾项移除
- 队列方法 (先进先出) : shift() 移除数组的第一项, unshift() 在数组第一项之前再添加一项
- 重排序方法: reverse() 反转 数组前后顺序颠倒 sort() 排序 默认从小到大, sort(),sort会循环数组,然后每一项进行比较,在比较时会把每一项转换成字符串, 然后再进行比较,所以会出现 1,14,2,23,3,4 这种形式,为了解决这种问题,sort() 函数可以传进来一个函数,函数返回 -1 : 第一个参数再第二个参数之前, 0 相等 , 1 : 第一个参数再第二个参数之后;
//字面量方式创建 (推荐) var list3 = [1, 2, 3, 11, 4, 5, 6, 7]; list3.sort(function(value, value2) { return value - value2; }); console.log(list3); //(8) [1, 2, 3, 4, 5, 6, 7, 11]
reverse() 与 sort() 会改变原数组, 返回改变后的数组
-
操作方法 : concat() 创建一个数组副本,然后把参数连接到数组副本的末尾
slice() 参数为起始位置,与结束位置, 返回数组的项在结束位置之前,不包含结束位置, 如果有参数为负数,那么实际就是用数组长度去加上这个负数,不改变原数组
splice() 参数(起始位置,要删除的项,要替换的项*) 以数组形式返回被删除的项 如果删除了0个 则返回空数组, 删除的项为0, 参数大于2个 则代表在当前位置插入.
- 位置方法 : indexOf()和 lastIndexOf() , 一个代表从前往后查找, 一个代表从后往前查找. 参数( 查找的项, 从XX位开始) 返回查找项所在位置, 如果没有返回 -1, indexOf与lastIndexOf 查找使用 ===
- 迭代方法 : 参数( 每一个项运行的函数, 该函数的作用域对象) 传入函数的参数( 当前项, 当前项索引, 原数组) 一共有5个迭代方法
var list = [1, 2, 3, 4, 5, 6]; //every 运行指定函数 如果每一项都为true都为 则返回true 否则 返回 false var result = list.every(function(item, index, array) { return item > 1; }); console.log(result); // false //some 运行指定函数 如果只要有一项都为true 则返回true 否则 返回 false result = list.some(function(item, index, array) { return item > 1; }); console.log(result); // true //filter 运行指定函数 返回值为true 当前项推入新数组 返回一个新数组 result = list.filter(function(item, index, array) { return item > 1; }); console.log(result); // [2, 3, 4, 5, 6] //map 运行指定函数 把函数运行结果 推入数组 返回一个新数组 result = list.map(function(item, index, array) { return item * 10; }); console.log(result); // [10, 20, 30, 40, 50, 60] //forEach 仅仅运行指定函数 没有返回值 也不能使用 continue break 跳出循环会报错 result = list.forEach(function(item, index, array) { if (item > 1) { return // 会跳出当前循环 类似 continue的效果 } }); console.log(result); // undefined
- 缩小方法 : reduce() 和 reduceRight() , 迭代数组 执行指定函数 最终返回一个值, 参数(上一个值,当前项,索引,原数组), reduce的迭代是从第二项开始的, 当第一次循环时 index的值为1 pre就等于array[0] cur等于array[1],当第二次循环时pre 等于之前函数的返回值
var list = [1, 2, 3, 4, 5, 6]; var result = list.reduce(function(pre,cur,index,array){ return pre + cur; console.log(index); // 1,2,3,4,5 }) console.log(result); // 21
3.Date类型: 创建Date对象 使用new关键字 var date = new Date(), 不传参会获取本地当前的时间, 当我们需要获得具体时间就必须传该日期的毫秒数,js函数内置了两个方法(也可手动调用),会根据传的参数自动决定调乃个方法 Date.parse()或者Date.UTC(), Date.parse() 传字符串, 具体形式有很多,自行选择, 如果不是日期会返回NaN, Date.UTC(), 就是把年月日以参数的形式 分开传进来, Date对象有许多函数,无非就是为了获取具体时间或者转换成字符串.
4.RegExp类型: js通过RegExp来支持正则表达式 创建有两种形式 /pattern/ 或者 new RegExp(" pattern","模式") 正则表达式原理可以看 这个文章 便于理解, 匹配模式有三个表示 g 全局模式(匹配到最后一个字符), i 不区分大小写 m多行模式,
- Reg实例属性:
- Reg实例方法:
exec() : 用来捕获组 参数(应用的字符串) , 返回第一个匹配项信息的数组, 如果没有返回null,返回数组有两个额外属性, input 当前应用的字符串 和 index 匹配项的索引, 在全局模式下 我们可以进行多次匹配 exec() 会根据reg对象的lastIndex来决定起始位置
test(): 接受参数(应用字符串) 匹配返回 true 否则返回 false
- Reg构造函数属性 : 这些属性是根据最近一次正则操作变化的 直接把书上的列出来
- 模式的局限性 : js的 正则缺少某些语言所持有的高级特性
5.Function类型: 每个函数就是function类型的实例, 函数名就是指向函数对象的指针
- 没有重载: 前文说了 函数名就是指针而已, 相同函数名 后声明会覆盖前声明的.
function fn() { console.log('1'); } function fn() { console.log('2'); } fn(); // 2
- 函数声明与函数表达式 : 函数声明与函数表达式 本质是有区别的 , 函数声明: 解析器会先读取函数声明,并把它提升到源代码的顶部,所以我们可以在任何函数声明之前使用他
fn(); // 1 function fn() { console.log('1'); }
而在函数表达式中: 解析器在执行代码时,才会被真正解析执行. 而下面代码会报错,由于他在一个初始化语句,解析器只有在执行到当前语句时才会给fn赋值, 而fn() 在 fn赋值之前执行所以会报错
fn(); var fn = function(){ console.log('1'); }
下方代码充分解释了函数声明与函数表达式的区别,fn() 调用位置不同 执行结果也不同
// fn(); // 2 此时函数表达式未赋值 所以此时调用的时 函数声明 var fn = function(){ console.log('1'); } function fn() { console.log('2'); } fn(); // 1 此时解析器先解析了函数声明 之后才是函数表达式 所以结果为1
- 作为值得函数 : 函数可以作为参数传递,也可作为返回值
var fn = function(fc) { console.log('函数表达式'); return function() { console.log('我作为函数 被返回了'); fc(); }; }; function handle() { console.log('我作为参数 被执行了'); } fn(handle)();
- 函数的内部属性: 除了argument外还有this, this代表函数执行的环境对象,全局作用域调用 this代表window
- 函数属性和方法: length() 代表接受命名参数的个数, 非继承方法 applay()和 call() 共同: 改变运行函数的作用域对象 区别: 前者 第二个参数为数组, 后者 多个参数形式. bind() 为函数绑定this, 再全局调用也为bind 绑定的对象.
6.基本包装类型: 每当读取一个基本类型的时候,后台会创建一个对应的基本包装类型,让我调用方法便于操作数据,读取后这个实例被销毁, 引用类型与基本包装类型区别就是生命周期的不同, 引用类型再代码执行时 存再内存中,离开作用后被垃圾回收机制收回,而基本包装类型仅存在于一行代码执行的瞬间,之后立即销毁, 所以我们对基本类型添加属性和方法是无效的. 那怕给基础类型添加属性,在执行时他就已经被销毁了. 一共有三种类型 Boolean, Number,String
- Number : toString() 参数: 代表返回string以几进制的形式, toFixed() 参数: 返回的字符串按几位小数显示(自动舍入), toExponential() 参数: 返回字符串按几位小数显示(e表示法),toPrecision() 参数: 返回字符串按位数显示(),(自动处理按fix 或者 exp方式显示)
- String :
var str = 'feng wang na chui'; //chatAt 参数代表 字符位置 返回字符位置所在的字符 var result = str.charAt(2); console.log(result); //n //chatCodeAt 参数代表 字符位置 返回字符位置所在字符的字符编码 result = str.charCodeAt(2); console.log(result); //110 //concat 参数代表 需要拼接的字符串 拼接位置在末尾 当然我们普遍使用 + 的形式 result = str.concat(' ming tian', '!!'); console.log(result); //feng wang na chui ming tian!! // slice substring 都是其实位置到结束位置(不包含结束位置) substr 时 开始位置到多少个字符 result = str.slice(2, 5); console.log(result); //ng result = str.substring(2, 5); console.log(result); //ng result = str.substr(2, 5); console.log(result); //ng wa // 负值和0 的情况下 没个函数都有区别 //slice 第二个参数为0时 返回空字符串 参数为负数 负数跟长度相加 再返回 result = str.slice(4, -1); console.log(result); // wang na chu //substring 第二个参数为0时 代表截取指定个数字符串 参数为负数 变为0 result = str.substring(4, -1); console.log(result); //feng //substr 第二个参数为0 代表截取0个字符,所以返回空 , 第一个参数为负数 负数与长度相加 第二个参数为负数 变为0 result = str.substr(-4); console.log(result); //chui //检索字符串 indexOf()从前往后 lastIndexOf()从后往前 参数1 检索的字符串 参数2 从哪个位置检索 //返回值 如果存在 则返回字符串的位置 如果不存在返回 -1 result = str.indexOf('chui'); console.log(result); //13 // trim() 删除字符串的前后空格 var test = ' lal '; result = test.trim(); console.log(result); //lal //大小写转换 result = str.toUpperCase(); //str.toLowerCase() console.log(result); //FENG WANG NA CHUI //match 参数是正则表达式或RegExp对象 返回一个数组 保存与正增表达式匹配的字符串 本质调用RegExp.exec()相同 result = str.match(/chui/); console.log(result); //["chui", index: 13, input: "feng wang na chui", groups: undefined] //search 参数是正则表达式或RegExp对象 如果没找到就返回-1 找到匹配正则 返回字符串位置 result = str.search(/chui/); console.log(result); //13 //replace 匹配字符串替换字符串 参数1 正则reg 或者 字符串 参数2 方法或者字符串 返回字符串 var text = '你好明天,明天'; //当参数1为字符串时 只改变匹配到的第一个 并根据第二个参数进行替换 result = text.replace('明', '昨'); console.log(result); //你好昨天,明天 //当参数1 为正则时 并且是全局模式 可以替换所有匹配 result = text.replace(/明/g, '昨'); console.log(result); //你好昨天,昨天 //当参数2 为字符串时可以使用 字符序列 插入到结果字符串中(详细使用看书) result = text.replace(/(明)/g, '风往哪吹$`'); console.log(result); //你好风往哪吹(明)天,风往哪吹(明)天 //当参数2为函数时 函数接收三个参数 匹配项 匹配项的位置 原始字符串 result = text.replace(/(明天)/g, function(matchStr, pos, text) { console.log(matchStr); // 明天 明天 console.log(pos); // 2 5 console.log(text); // 明天 明天 return '昨'; }); console.log(result); //你好昨天,昨天 //split() 根据指定字符 分割字符串 参数1 字符串或正则 参数2 返回数组长度 返回分割后的数组 result = str.split(' '); console.log(result); //0: "feng" 1: "wang" 2: "na" 3: "chui" //localeCompare 比较字符串 zlack如果该字符在前则返回1 相等返回0 再后面返回-1 result = str.localeCompare('zlack'); console.log(result);//-1 // String.fromCharCode() 根据字符编码输出字符串 result = String.fromCharCode(111,111); console.log(result);//oo
7.单体内置对象: 不依赖宿主环境 再程序执行前就已经存在 Global和Math
- Global: 不属于其他对象的属性和方法,就是global对象的方法和属性(全局作用域中定义), 一些前文没讲过的方法
//URI编码方法(uri包含url) var url = 'https://home.fire foxch ina.cn/'; var encodeUrl = 'https%3A%2F%2Fhome.fire%20%20foxch%20%20ina.cn%2F'; // encodeURI 会用utf-8编码替换特殊字符 不会对本身属于uri的特殊字符进行替换 var newUrl = encodeURI(url); console.log(newUrl); //https://home.fire%20%20foxch%20%20ina.cn/ // encodeURIComponent 会用utf-8编码替换特殊字符 全部替换 newUrl = encodeURIComponent(url); console.log(newUrl); //https%3A%2F%2Fhome.fire%20%20foxch%20%20ina.cn%2F //decodeURI 对uri进行解码 但是不会对uri自带的特殊字符解码 newUrl = decodeURI(encodeUrl); console.log(newUrl); //https%3A%2F%2Fhome.fire foxch ina.cn%2F //decodeURIComponent 对uri进行解码 全部解码 newUrl = decodeURIComponent(encodeUrl); console.log(newUrl); //https://home.fire foxch ina.cn/ //eval() 参数字符串:要执行的语句 再eval中声明的变量 外部无法使用,他们只要eval执行的时候才会被创建 eval('console.log("你好明天")'); var str = '(function(){var beijing = "beijing"; console.log(beijing);})()' eval(str) console.log(beijing);//beijing is not defined
- Math: Math对象提供了一些数学方法,和属性.,有许多方法就不一一列举了.
//max() 和 min() 检测最大值或者最小值 var num = Math.max(1, 2, 3, 4, 5); console.log(num); //5 //检测数组 num = Math.max.apply(Math, [1, 2, 3, 4, 5]); console.log(num); //5 //四舍五入 ceil()天花板(向上取整) floor()地板(向下取整) round()标准四舍五入 num = Math.ceil(4.5); console.log(num); //5 num = Math.floor(4); console.log(num); //4 num = Math.round(4.5); console.log(num); // 5 //随机 random() 返回一个0到1之间的数 不包括 0 和 1 num = Math.random(); console.log(num); //0.17385311030185568 //取1-10之间的整数 num = Math.floor(Math.random() * 10); console.log(num);