你不知道的JavaScript----类型

目录

概念

类型 

内置类型

值和类型

undefined与undeclared

 typeof与undeclared、typeof安全防范机制

检测变量名在局部是否可用 


概念

大多数开发者认为,像JavaScript这样的动态语言是没有类型(type)的。

这里的动态类型,可以理解成变量的类型是动态的,可以在运行时随时改变,也可以理解成变量没有类型的概念,只有值才有类型。总之,变量所指向的内存存储的值,类型可以随便变化,以区别于静态类型语言

静态语言

强类型相对于弱类型来说,不允许隐式类型转换。声明了一个变量以后,不能改变它的类型的语言称为静态语言。

类型 

我们必须掌握 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 检测数据类型

undefined、string、number、boolean、symbol、object(引用类型)6种类型有相应的同名字符串值与其对应,比如: typeof undefined === "undefined"。而余下的1种类型null表现却有差异: typeof null === "object",这是JavaScript最初就存在的bug。
bug原因: JavaScript的值是由一个类型标签和实际值表示的,类型标签占3位,比如: 000就表示object。JavaScript中的null表示机器码中的NULL(空指针),而在大多数平台下NULL是0x00(十六进制),所以null是00000000,标签位也是000,故 typeof null === "object"。

    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(a, b) { }
    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

  • function(函数)也是 JavaScript 的一个内置类型。然而查阅规范就会知道,它实际上是 object 的一个“子类型”。具体来说,函数是“可调用对象”,它有一个内部属性 [[Call]],该属性使其可以被调用。而且函数还可以拥有属性length值为传入的参数
  • 数组也是对象。确切地说,它也是 object 的一个“子类型”,数组的元素按数字顺序来进行索引(而非普通像对象那样通过键值对),其 length 属性是元素的个数。
  • typeof返回值是一个字符串

要获取一个函数的形参,使用函数的length属性就可以了。获取实参的话,就要用到arguments属性

值和类型

javascript的变量名没有类型,变量的值才有类型

let a = "str";
console.log(typeof a); // "string"
a = 1;
console.log(typeof a); // "number"
/* 
    同是变量名a,但是 typeof 的时候输出不同的值,输出的值与变量值的类型值一一对应
    说明javascript不检验变量名的值,检验的是变量值
*/

undefined与undeclared

已在作用域中声明但还没有赋值的变量,是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。

采用 let 和 const 声明的全局变量并不会挂载到 window 上,所以用 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());
}

 


版权声明:本文为qq_63358859原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。