Javascript中使用typeof能得到哪些类型?

250 阅读4分钟

前言

在 JavaScript 中,我们经常需要对不同的数据类型进行判断和处理。JavaScript 提供了多种方法来进行类型判断,包括 typeof、instanceof、Object.prototype.toString.call() 和 Array.isArray() 等。本文将深入探讨这些方法的使用和特点。

typeof 操作符

typeof 操作符是用来判断一个值的类型的基本方法。它返回一个表示该值类型的字符串。在 JavaScript 中,typeof 可以准确地判断除 null 之外的原始类型,并且可以判断一个值是否为函数类型。

console.log(typeof 'hello');//string
console.log(typeof 123);  //number
console.log(typeof true);//布尔
console.log(typeof undefined);//underfined
console.log(typeof Symbol(1));  //symbol
console.log(typeof 123n);//bigint
console.log(typeof null); // object          null被错误判断为object
console.log(typeof ({}));  // object
console.log(typeof ([]));  // object
console.log(typeof (new Date())); // object
console.log(typeof (function () { }))  // function

问:可以用function举一个例子吗?

什么是function?

在JavaScript中,function 是一个关键字,用于定义一个函数。函数是可重用的代码块,它执行一个特定的任务或一组相关的任务。你可以在程序中的多个地方调用(或“调用”)同一个函数,而不需要重复编写相同的代码。

以下是一个简单的JavaScript函数的示例:

function greet(name) {  
    return "Hello, " + name + "!";  
}  
var message = greet("World");  
console.log(message); // 输出 "Hello, World!"  

在上述代码中,greet 是一个函数,它接受一个参数 name 并返回一个字符串。你可以多次调用这个函数,传入不同的 name 值,它将返回不同的问候语。

function的原型:

在js中原型是有一定的重要性的,Function(构造函数) 与 Function.prototype(原型)又是相生相伴的关系,从构造函数层面,它已经比 Array、String、Number 等重要了,虽然比不上对象 Object,但也是仅次于它的存在

不仅如此,函数还能做很多事情。首先,它是个对象,这一知识点我们在 一切皆对象 中解释过,所以它和对象一样,也有属性,也可以赋值给变量。除此之外,函数可以自身当作参数传递,也具有返回值的特性

总之,对象能做的它都能做,它还有自身的特性,能做更多的事情(例如:能作为参数传递,有返回值)

什么是原型?以及原型链是什么?

我们先来了解下面引用类型的四个规则:

1、引用类型,都具有对象特性,即可自由扩展属性。

2、引用类型,都有一个隐式原型 __proto__ 属性,属性值是一个普通的对象。

3、引用类型,隐式原型 __proto__ 的属性值指向它的构造函数的显式原型 prototype 属性值。

4、当你试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么它会去它的隐式原型 __proto__(也就是它的构造函数的显式原型 prototype)中寻找。

引用类型:Object、Array、Function、Date、RegExp。这里我姑且称 proto 为隐式原型,没有官方中文叫法,大家都瞎叫居多。

下面我们逐一验证上面几个规则,就会慢慢地理解原型和原型链。

规则一

引用类型,都具有对象特性,即可自由扩展属性:

const obj = {}
const arr = []
const fn = function () { }

obj.a = 1
arr.a = 1
fn.a = 1

console.log(obj.a) // 1
console.log(arr.a) // 1
console.log(fn.a) // 1


规则二

引用类型,都有一个隐式原型 __proto__ 属性,属性值是一个普通的对象:

const obj = {};
const arr = [];
const fn = function() {}

console.log('obj.__proto__', obj.__proto__);
console.log('arr.__proto__', arr.__proto__);
console.log('fn.__proto__', fn.__proto__);

规则三

引用类型,隐式原型 __proto__ 的属性值指向它的构造函数的显式原型 prototype 属性值:

const obj = {};
const arr = [];
const fn = function() {}

obj.__proto__ == Object.prototype // true
arr.__proto__ === Array.prototype // true
fn.__proto__ == Function.prototype // true

规则四

当你试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么它会去它的隐式原型 __proto__(也就是它的构造函数的显式原型 prototype)中寻找:

const obj = { a:1 }
obj.toString
// ƒ toString() { [native code] }

首先, obj 对象并没有 toString 属性,之所以能获取到 toString 属性,是遵循了第四条规则,从它的构造函数 Object 的 prototype 里去获取。

原型 __proto__ 的属性值指向它的构造函数

下面是一个示例的构造函数:

首先通过function定义一个关键字person函数,原型 prototype 继承函数,然后再吧new的person抛出去调用

function Person(name) {
    this.name = name;
}
Person.prototype.sayHello = function() {
    console.log("Hello, my name is " + this.name);
};
var person1 = new Person('Alice');
person1.sayHello(); // 输出:"Hello, my name is Alice"

原型有四个规则记住,如下:

javaScript一切皆为对象,函数也属于对象

所有对象都含有_proto_

只有函数才有prototype

所有函数的默认原型都是object实例对象

函数对象都是由function函数生成的,看下例:

function fn(){}

fn._proto_ === Function.prototype //true
fn instanceof function //true
fn instanceof Object //true

mmexport1703501384002.png

const arr = new Array(1,2,3)
arr.reverse() //翻转
arr.sort() //排序
console.log(arr._proro_ === Array.prototype) //true

总结:

1.函数都有prototype属性,称之为原型,也称为原型对象以及函数定义的关键字, 原型可以放一些属性和方法,共享给实例对象使用 原型可以做继承

2.原型链:对象都有_proto_属性,这个属性指向它的原型对象,原型对象也是对象,也有_proto_属性,指向原型对象的原型对象,这样一层一层形成链式结构称为原型链,最顶层找不到则返回null