JavaScript 学习笔记 之 原生函数

原生函数是什么

JavaScript的原生函数也叫内建函数

例如 String(),Number(),Boolean()等

原生函数可以被当做构造函数来使用

但通过构造函数(如new String("abc"))创建出来的是封装了基本类型值("abc")的封装对象

		var abc = new String("abc");
		console.log(typeof abc); //object 不是string

[[class]]

[[class]]是所有typeof返回值为"object"的对象的一个内部属性(函数的typeof返回值为"function"),这个属性无法被直接访问

但可以通过Object.prototype.toString(..)来查看,可以把它看做是一个内部的分类

		Object.prototype.toString.call(abc);//[object String]

多数情况下,对象内部的[[class]]属性和创建改对象的内建原生构造函数相对应

		Object.prototype.toString.call([1, 2, 3]); //[object Array]

但并非总是如此

		Object.prototype.toString.call(undefined); //[object Undefined]

可以看到undefined不存在Undefined()这样的原生构造函数,但是[[class]]仍然是"Undefined"(null的[[class]]是"Null")

而其他的基本类型则存在一个被称为包装(boxing)的行为

		Object.prototype.toString.call("123"); //[object String]
		Object.prototype.toString.call(123); //[object Number]
		Object.prototype.toString.call(true); //[object Boolean]

上例中基本类型被各自的封装对象自动包装,所以它们的内部[[Class]]值分别为"String","Number","Boolean"

封装对象包装

由于基本类型没有.length这样的属性和.toString()这样的方法

需要通过封装对象才能访问,此时JavaScript会自动为基本类型值包装(box或者wrap)一个封装对象

		var a = "abc";
		a.length; //3

想要自行封装基本类型值可以用Object(..)函数(不加new)

拆封

由于封装对象是一个对象,所以不管基本类型值是什么,进行判断的时候返回的都是一个真值

当我们需要得到封装对象中的基本类型值时,可以用valueOf(..)函数

		var a = Object("abc");
		console.log(a.valueOf());//abc

在需要用到封装函数中的基本类型值的时候会发生隐式解封

		var a = Object("abc");
		var b = a + "";
		console.log(b, typeof b); //abc string

 

原生函数作为构造函数

使用Array(..)构造一个数组和直接声明一个数组的效果是一样的,创建的值都是通过封装对象来包装

使用Array(..)构造函数时候带new和不带new效果是一样的,不带new的时候会自动补上

只带一个数字参数的时候,该参数会被当做预设长度,而不是当做数组中的一个元素

如果一个数组没有任何单元,但是length属性却显示有,这样会出现空单元的情况

		var a = new Array(3);
		console.log(a); //(3) [empty × 3]

我们将包含至少一个空单元的数组称之为稀疏数组

在某些方法中空单元的行为和undefined类似,但在另一些方法中又完全不同

		var a = new Array(3);
		var b = [undefined, undefined, undefined];
		console.log(a); //(3) [empty × 3]
		console.log(b); //(3) [undefined, undefined, undefined]
		console.log(
			a.join("-"), //--
			b.join("-") //--
		);
		console.log(
			a.map(function(value, index) {
				return index;
			}), //(3) [empty × 3] 
			b.map(function(value, index) {
				return index;
			}) //(3) [0, 1, 2]
		);

这是因为join方法会先假定数组不为空,然后通过length来遍历

而map方法则不会

由于空单元存在的种种问题,因此我们不建议在任何情况下创建和使用空单元

我们可以用另一种方法来更安全创建undefined值的数组

		var a = Array.apply(null, {
			length: 3
		});
		console.log(a); //(3) [undefined, undefined, undefined]

Array.apply把{length:3}作为参数调用Array()方法

在传入参数时假设apply有个for循环来遍历传入的类数组对象

从0开始循环到length

但是由于传入的类数组对象中并没有[0],[1],[2]等属性,于是返回的是undefined

因此实际上执行的就变成了Array(undefined,undefined,undefined)

原生函数的原型

原生构造函数也有自己的.prototype对象,如Array.prototype

这些对象包含其子对象所特有的行为特征

比如String.prototype.indexOf(..)

根据文档约定,这类方法一般简写为String#indexOf(..)

而原生的函数的原型同样也是不错的默认值

因为类似于Array.prototype已经被创建过一次了

如果将默认值设定为 [] 的话会导致资源的浪费,因为每次使用都需要创建一次

但是如果默认值随后会改变的话,就不要使用这种方法

因为修改原型会导致很多问题

猜你喜欢

转载自blog.csdn.net/Aproducer/article/details/82807385