JavaScript高级程序设计-CH5

44次阅读

共计 4949 个字符,预计需要花费 13 分钟才能阅读完成。

第五章、引用类型

一共七种引用类型:

  • Object:可通过 new 和字面量两种方法来创建。在使用字面量表示法的时候,并不会调用对象的构造函数
  • Array:17 种常用方法; 同 object 一样可通过 new 和字面量两种方法来创建。
  • Date:
  • RegExp:
  • Function:函数名指针,this 指针,prototype 原型链,apply()、call()
  • 基本包装类型(Boolean, Number, String):
  • 单体内置对象(Global, Math):

1.Object 类型

两种访问对象属性的方法:

  1. person[“name”];
  2. person.name;

通常建议使用 点表示法
方括号表示方法 主要优点:通过变量来访问属性

2.Array 类型

·[].length 属性不是只读的,可以读取,修改,扩大 / 新增,缩小 / 删除。

Array 对象方法简介 (17 = 2+2+2+2+2+5+2)

  • 栈方法(LIFO): push(), pop()
  • 队列方法 (FIFO): push(), shift()
    另外还有 unshift()
  • 重排序方法: reverse(), sort()
    调用的是 toString 类型,所以比较的是 ascii 码
  • 操作方法: concat(), slice()
  • 位置方法: indexOf(), lastIndexOf();
    使用的是全等号
  • 迭代方法: every(), filter(), some(), forEach(), map()
  • 归并方法: reduce(), reduceRight()

经典问题: 检测对象是否是数组 arr instanceof Array?

本质依赖于构造函数,受到执行环境影响。所以,ES5 当中是新增了 Array.isArray(arr)方法。

经典问题: 类型判别?

  • typeof

null 是对象空指针,适合判断基本类型变量,不适合判断引用类型(都返回 object),比如自定义的对象类型

  • instanceof

如果有多个框架,那就存在两个以上不同的全局执行环境,那就会有两个不同版本的 Array 的构造函数。
而且返回的是 true/false

  • constructor

高效但是危险 Null or Undefined

  • Object.prototype.toString.call() 建议使用

Array 对象方法详解

方法前面带 * 表示不修改原来数组

  • *join() 所有元素拼接成一个字符串,返回字符串
['Fire', 'Air', 'Water'].join('-')); //"Fire-Air-Water"

逆方法:String.prototype.split()

  • *slice()切片:从已有的数组中返回选定的元素
var animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
animals.slice(2);// Array ["camel", "duck", "elephant"]
animals.slice(2, 4);//Array ["camel", "duck"]
animals.slice(-2, -1) <==> animals.slice(3, 4) // 前提条件:长度为 5 
  • *concat()连接两个或多个数组, 返回新数组
arr1.concat(arr2)
  • splice()从数组中添加 / 删除项目,返回被删除的元素
months.splice(1, 0, 'Feb');  // inserts at index 1
months.splice(4, 1, 'May');  // replaces 1 element at index 4
  • pop() 删除数组最后一个元素,返回被删除的元素。如果数组为空,则不改变数组,返回 undefined
  • shift()把数组的第一个元素删除,返回第一个元素的值。若空数组,不进行任何操作,返回 undefined
  • push()向数组末尾添加一个或多个元素返回新数组的长度
  • unshift()向数组的开头添加一个或多个元素,返回新数组的长度
  • reverse()颠倒元素顺序,返回该数组
  • sort()根据 ascii 进行排序,返回该数组
[0,1,5,10,15].sort(); //[0,1,10,15,5]
[0,1,5,10,15].sort((v1,v2) => {return (v1<=v2)? -1:1; }); //[0,1,5,10,15]
  • *toString() 返回数组的字符串形式

toLocalString()

Date 类型

var start = Date.now();
// do something
var end = Date.now();
costTime = stop -start;

RegExp 类型

var pattern = /[bc]at/gi <==> new RegExp("[bc]at","gi"); // 大小写不敏感,全局匹配 bat 或者 cat
var matches = pattern.exec("bat is not a cat");

Function 类型

函数名仅仅是指向函数的指针,不会与某个函数绑定(即变量法的函数引用是可以被覆盖的)
注意函数声明提升(function declaratioin hoisting)和变量提升是有区别的。

//unexpected identifier
alert(sum(1,1));
var sum = function(v1, v2){return v1 + v2;}
//ok
alert(sum1(1,1));
function sum1(v1, v2){return v1 + v2;}

内部对象,this 指针和类数组对象 arguments

  1. 类数组对象 arguments

严格模式下 arguments.callee 和 arguments.caller 无效

  1. this 指针

注意作用域

window.color = "red";
var o = {color : "blue"};
function sayColor(){alert(this.color);
}
sayColor(); //red
o.sayColor() = sayColor();
o.sayColor(); //blue

Function 的 prototype 属性、内部方法

fn.length 属性表示 fn 希望接收的参数的个数
prototype 属性
保存所有实例方法的真正所在,换言之甚至 toString(),valueOf()等方法都在 prototype 之下。
在创建自定义引用类型以及实现继承时,prototype 极为重要。并且它是不可枚举的,因此 for-in 无法发现。
内部方法
每个 fn 都包含 apply()和 call(),apply()固定接收两个参数,作用域和 arguments,call()接收多个参数,第一个是作用域。
这两个函数可以用来传参数,但是真正的作用是 扩充作用域:如此对象和方法不需要有任何的耦合关系

window.color = "red";
var o = {color : "blue"};
function sayColor(){alert(this.color);
}
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue

基本包装类型(Boolean, Number, String)

我们知道,基本类型值不是对象,因此逻辑上应该是没有方法的。但是实际当中 Boolean, Number, String 这三种在访问 / 读取的时候,会进入一种“读取模式”:创建实例 =》实例上调用方法 =》销毁实例
这种读取模式是 隐性 的,并且不建议显示调用。因为会让人分不清是在处理基本类型还是引用类型。

  • 直接调用基本包装类型的构造函数,返回实例都属于 object

    var value = Number("25");
    alert(typeof value);// number
    var value2 = new Number("25");
    alert(typeof value2);// object
  • new Object()这个构造函数是会根据参数返回相应的基本包装类型的实例。说白了就是工厂模式呗

    var obj = new Object("test");
    alert(obj instanceof String) //true

Boolean 基本包装对象

很烂很烂很烂,不要去用

Number 基本包装对象

num.toFixed(2); // 精确两位小数
num.toExponential(2) // 科学计数法保留两位小数
num.toPrecision(2)// 看哪种格式方便,自动返回 fixed 还是指数形式

String 基本包装对象

  • 字符方法:str.charAt(2); str[2]
  • 操作方法:str.concat(); str.slice(), str.substring, str.substr()
    后面三个都是返回一个新串串。都可以接受两个参数,slice()和 substring()是[start,end],而 substr 是[start,length]
  • 位置方法:str.indexOf(); str.lastIndexOf()
    如果接受第二个参数,表示从第几位开始查起
  • trim 方法:去除开头结尾的空格
  • 大小写转换方法:toUpperCase(); toLowerCase()
    少数语言(比如土耳其语)会为 Unicode 来应用特殊的转换规则,所以最好用 toLocalUpperCase()
  • 模式匹配方法:str.match(pattern); str.replace(), str.split(),str.includes()

    var mathces = pattern.exec(str) <==> str.match(pattern);
    var str = "cat,bat,fat"; //pattern 一定要用全局模式 g
    alert(str.replace(/(.at)/g, "word ($1)") ); //word (cat), word (bat), word (fat)
  • padding 方法: str.padStart(), str.padEnd();

    const fullNumber = '2034399002125581';
    const last4Digits = fullNumber.slice(-4);
    const maskedNumber = last4Digits.padStart(fullNumber.length, '*'); //"************5581"

单体内置对象(Global, Math)

由 ECMAScript 实现提供的、不依赖于宿主环境的对象。

Global 对象

  • URI 编码方法:encodeURI(), encodeURIComponent()
//http://www.w3school.com.cn/My%20first/
encodeURI("http://www.w3school.com.cn/My first/")
// http%3A%2F%2Fwww.w3school.com.cn%2FMy%20first%2F
encodeURIComponent("http://www.w3school.com.cn/My first/"
  • eval()方法,执行字符串代码
var msg = "hello world";
eval("alert(msg)");
  • window 对象
    web 浏览器都是把 Global 对象作为 window 对象的一部分来实现的。因此,在全局作用域中声明的所有变量和函数,都成为了 window 对象的属性

Math 对象

  • Math 对象的属性

Math.E 常量 e,Math.PI 常量圆周率

  • min(), max()接受多参数
// 这个技巧的关键是把 Math 对象作为第一个参数,从而正确地设置 this 指针,然后吧 values 数组作为参数
var values = [1,2,3,4,5];
var max = Math.max.apply(Math, values);
  • 舍入方法
Math.ceil(); // 向上取整
Math.floor(); // 向下取整
Math.round(); // 四舍五入整数
  • 随机数 random()

本质是返回 (0,1) 的一个随机数
值 = Math.floor(Math.random() * 可能值的总数 + 第一个可能的值 );

  • 其他方法
Math.abs(num);
Math.pow(num,power); //num^power
三角函数、反三角函数等

正文完
 0