文章目录
类型
我们必须掌握 JavaScript 中的各个类型及其内在行为。几乎所有的 JavaScript 程序都会涉及某种形式的强制类型转换。
let num = 3;
let str = "3";
console.log(str + num); // "33" num会被强制转换为string类型
内置类型
基本类型:undefined,boolen,number,string,符号symbol(es6新增)
>>假值类型:null
复杂类型:对象object
>>子类型Function,Array
说明
- 使用typeof运算符来查看值的类型,只有null返回的是object类型,出了问题。正确的返回结果应该是 “null”,但这个 bug 由来已久,在 JavaScript 中已经存在了将近二十年,也许永远也不会修复,因为这牵涉到太多的 Web 系统,“修复”它会产生更多的bug,令许多系统无法正常工作。
- function(函数)也是 JavaScript 的一个内置类型。然而查阅规范就会知道,它实际上是 object 的一个“子类型”。具体来说,函数是“可调用对象”,它有一个内部属性 [[Call]],该属性使其可以被调用。而且函数还可以拥有属性length值为传入的参数
- 数组也是对象。确切地说,它也是 object 的一个“子类型”,数组的元素按数字顺序来进行索引(而非普通像对象那样通过键值对),其 length 属性是元素的个数。
console.log(typeof 1 === "number");//true
console.log(typeof "string" === "string");//true
console.log(typeof undefined === "undefined");//true
console.log(typeof true === "boolean");//true
console.log(typeof {} === "object");//true
console.log(typeof Symbol() === "symbol");//true
console.log(typeof null === "null");//false
console.log(typeof null === "object");//true
const fn = function fn() {}
console.log(typeof fn === "function");//true
console.log(fn.length);//2
console.log(typeof [1,2,3] === "object");//true
console.log([1,2,3].length);//3
判断值是否是null
const nl = null;
const fn = function fn(nl) {
if (!nl && typeof nl === "object") {
return true;
}
return false;
}
console.log(fn(nl)); // true
值和类型
javascript的变量名没有类型,变量的值才有类型
let a = "str";
console.log(typeof a); // "string"
a = 1;
console.log(typeof a); // "number"
/*
同是变量名a,但是 typeof 的时候输出不同的值,输出的值与变量值的类型值一一对应
说明javascript不检验变量名的值,检验的是变量值
*/
undefined与undeclared
在js中,当一个变量声明了但是还没有赋值的时候,此时这个变量的值默认会是undefined。
但是我们也可以直接给它赋值一个undefined。
let varl1;
let varl2 = "str";
varl2 = varl1;
console.log(varl1, varl2); // undefined undefined
console.log(typeof varl1); // undefined
console.log(typeof varl2); // undefined
但是当我们typeof一个未声明的变量时,还是输出的undefined,按理来说应该输出undeclared或者报错。
但是没有报错,因为typeof有安全防范机制,但是输出的值是undefined,还是会对我们造成一定的困扰。
console.log(typeof a); // undefined
typeof与undeclared、typeof安全防范机制
检测全局变量是否可用以及避免程序一部分报错
多个脚本文件会在共享的全局命名空间中加载变量。理论上,全局命名空间中不应该有变量存在,所有东西都应该被封装到模块和私有或独立的命名空间中,然而不切实际。
举个简单的例子,在程序中使用全局变量 DEBUG 作为“调试模式”的开关。在输出调试信息到控制台之前,我们会检查 DEBUG 变量是否已被声明。顶层的全局变量声明 var DEBUG =true 只在 debug.js 文件中才有,而该文件只在开发和测试时才被加载到浏览器,在生产环境中不予加载。问题是如何在程序中检查全局变量 DEBUG 才不会出现 ReferenceError 错误。这时 typeof 的安全防范机制就成了我们的好帮手:
// 这样会抛出错误,浏览器报错DEBUG is not defined
if (DEBUG) {
console.log( "Debugging is starting" );
}
// 这样是安全的
if (typeof DEBUG !== "undefined") {
console.log( "Debugging is starting" );
}
不仅对用户定义的变量(比如 DEBUG)有用,对内建的 API 也有帮助:
//判断这个变量名是否在当前作用域中能够使用
if (typeof atob === "undefined") {
atob = function() { /*..*/ };
}
还有一种不用通过 typeof 的安全防范机制的方法,就是检查所有全局变量是否是全局对象的属性,浏览器中的全局对象是 window。这种方法有一个缺点:当代码需要运行在多种 JavaScript环境中时(不仅仅是浏览器,还有服务器端,如 node.js 等),此时全局对象并非总是window。
if (window.DEBUG) {
// ..
}
if (!window.atob) {
// ..
}
检测变量名在局部是否可用
虽然很少见,但是如果想让自己写的代码可以被其他人复制使用,并且保证如果在别人的代码作用域中有同名变量就用别人的,否则就自己创建。
const callback = function () {
return "我的程序中已有了"
}
if (typeof callback !== 'undefined') {
let varl = typeof callback !== 'undefined' ? callback : function () {
return "typeof安全保护机制"
};
console.log(varl());
}