数据与声明
基本类型
基本类型(7 个):Null
Undefined
Number
Boolean
Symbol
String
BigInt
js
var a = null;
console.log(Reflect.toString.call(a)); // '[object Null]'
var a = undefined;
console.log(Reflect.toString.call(a)); // [object Undefined]
var a = Symbol("a");
console.log(Reflect.toString.call(a)); // [object Symbol]
var a = BigInt(1);
console.log(Reflect.toString.call(a)); // [object BigInt]
var a = new Number(1);
var a = 1;
console.log(Reflect.toString.call(a)); // [object Number]
var a = new Boolean(true);
var a = true;
console.log(Reflect.toString.call(a)); // [object Boolean]
var a = new String("a");
var a = "a";
console.log(Reflect.toString.call(a)); // [object String]
var a = null;
console.log(Reflect.toString.call(a)); // '[object Null]'
var a = undefined;
console.log(Reflect.toString.call(a)); // [object Undefined]
var a = Symbol("a");
console.log(Reflect.toString.call(a)); // [object Symbol]
var a = BigInt(1);
console.log(Reflect.toString.call(a)); // [object BigInt]
var a = new Number(1);
var a = 1;
console.log(Reflect.toString.call(a)); // [object Number]
var a = new Boolean(true);
var a = true;
console.log(Reflect.toString.call(a)); // [object Boolean]
var a = new String("a");
var a = "a";
console.log(Reflect.toString.call(a)); // [object String]
引用类型
引用类型(6 个):Object Function Map Set WeakMap WeakSet
js
var a = {};
var a = new Object();
var a = Object.create({});
console.log(Reflect.toString.call(a)); // '[object Object]'
var a = () => {};
var a = function () {};
var a = new Function();
var a = class {};
console.log(Reflect.toString.call(a)); // [object Function]
var a = new Map();
console.log(Reflect.toString.call(a)); // [object Map]
var a = new Set();
console.log(Reflect.toString.call(a)); // [object Set]
var a = new WeakMap();
console.log(Reflect.toString.call(a)); // [object WeakMap]
var a = new WeakSet();
console.log(Reflect.toString.call(a)); // [object WeakSet]
var a = {};
var a = new Object();
var a = Object.create({});
console.log(Reflect.toString.call(a)); // '[object Object]'
var a = () => {};
var a = function () {};
var a = new Function();
var a = class {};
console.log(Reflect.toString.call(a)); // [object Function]
var a = new Map();
console.log(Reflect.toString.call(a)); // [object Map]
var a = new Set();
console.log(Reflect.toString.call(a)); // [object Set]
var a = new WeakMap();
console.log(Reflect.toString.call(a)); // [object WeakMap]
var a = new WeakSet();
console.log(Reflect.toString.call(a)); // [object WeakSet]
其他数据
js
var a = NaN;
console.log(Reflect.toString.call(a)); // '[object Number]'
var a = Infinity;
console.log(Reflect.toString.call(a)); // '[object Number]'
var a = -Infinity;
console.log(Reflect.toString.call(a)); // '[object Number]'
var a = new Error();
console.log(Reflect.toString.call(a)); // '[object Error]'
var a = BigInt("9007199254740991");
console.log(Reflect.toString.call(a)); // '[object BigInt]'
var a = new Date();
console.log(Reflect.toString.call(a)); // '[object Date]'
var a = new RegExp();
console.log(Reflect.toString.call(a)); // '[object RegExp]'
var a = new Promise(() => {});
console.log(Reflect.toString.call(a)); // '[object Promise]'
var a = new Proxy({}, {});
console.log(Reflect.toString.call(a)); // '[object Object]'
/* 等等 */
var a = NaN;
console.log(Reflect.toString.call(a)); // '[object Number]'
var a = Infinity;
console.log(Reflect.toString.call(a)); // '[object Number]'
var a = -Infinity;
console.log(Reflect.toString.call(a)); // '[object Number]'
var a = new Error();
console.log(Reflect.toString.call(a)); // '[object Error]'
var a = BigInt("9007199254740991");
console.log(Reflect.toString.call(a)); // '[object BigInt]'
var a = new Date();
console.log(Reflect.toString.call(a)); // '[object Date]'
var a = new RegExp();
console.log(Reflect.toString.call(a)); // '[object RegExp]'
var a = new Promise(() => {});
console.log(Reflect.toString.call(a)); // '[object Promise]'
var a = new Proxy({}, {});
console.log(Reflect.toString.call(a)); // '[object Object]'
/* 等等 */
作用域
在 JS 中,变量的作用域是由块和函数划分的,有全局作用域、局部作用域、块级作用域之分。
在 JS 中,变量查找访问的作用域顺序是 块、局部、全局,也就是作用域链规定好了从里到外的顺序。
全局作用域
:声明在全局的变量或者不使用var
声明的变量在整个程序中都是可用的。局部作用域
:声明在函数体内的变量,在整个函数执行环境和其子函数内都是可用的,但是在函数外访问不到。块级作用域
:可以让变量只在一块代码内生效。块级作用域可以通过let
和const
来声明。
变量声明
四种方式:默认方式
、var
、let
、const
。
默认声明
js
a1 = Symbol(); // 默认声明
console.log(a1 === globalThis.a1); // true
(function fn() {
a2 = Symbol();
})();
console.log(a2 === globalThis.a2); // true
{
a3 = Symbol();
}
console.log(a3 === globalThis.a3); // true
a1 = Symbol(); // 默认声明
console.log(a1 === globalThis.a1); // true
(function fn() {
a2 = Symbol();
})();
console.log(a2 === globalThis.a2); // true
{
a3 = Symbol();
}
console.log(a3 === globalThis.a3); // true
var
js
console.log("变量提升: %s", a5); // 变量提升: undefined ✅
var a5 = Symbol(1);
var a5 = Symbol(2); // 重复声明 ✅
a5 = Symbol(3); // 多次赋值 ✅
var a51; // 空值声明 ✅
console.log("变量提升: %s", a5); // 变量提升: undefined ✅
var a5 = Symbol(1);
var a5 = Symbol(2); // 重复声明 ✅
a5 = Symbol(3); // 多次赋值 ✅
var a51; // 空值声明 ✅
let
js
console.log(a6); // 变量提升不支持 ❌ Uncaught ReferenceError: a6 is not defined
let a6 = Symbol(1);
let a6 = Symbol(2); // 重复声明不支持 ❌ Uncaught SyntaxError: Identifier 'a6' has already been declared
a6 = Symbol(3); // 多次赋值 ✅
let a61; // 空值声明 ✅
// 特殊
window.aa = 2;
window.bb = 2;
var aa = 0;
let bb = 0;
console.log(aa); // 2
console.log(bb); // 0
console.log(window.aa); // 2
console.log(window.bb); // 2
console.log(a6); // 变量提升不支持 ❌ Uncaught ReferenceError: a6 is not defined
let a6 = Symbol(1);
let a6 = Symbol(2); // 重复声明不支持 ❌ Uncaught SyntaxError: Identifier 'a6' has already been declared
a6 = Symbol(3); // 多次赋值 ✅
let a61; // 空值声明 ✅
// 特殊
window.aa = 2;
window.bb = 2;
var aa = 0;
let bb = 0;
console.log(aa); // 2
console.log(bb); // 0
console.log(window.aa); // 2
console.log(window.bb); // 2
const
js
console.log(a8); // 变量提升不支持 ❌ Uncaught ReferenceError: a8 is not defined
const a8 = Symbol(1);
const a8 = Symbol(2); // 重复声明不支持 ❌ Uncaught SyntaxError: Identifier 'a8' has already been declared
a8 = Symbol(3); // 多次赋值不支持 ❌ Uncaught TypeError: Assignment to constant variable.
const a81; // 空值声明不支持 ❌ Uncaught SyntaxError: Missing initializer in const declaration
console.log(a8); // 变量提升不支持 ❌ Uncaught ReferenceError: a8 is not defined
const a8 = Symbol(1);
const a8 = Symbol(2); // 重复声明不支持 ❌ Uncaught SyntaxError: Identifier 'a8' has already been declared
a8 = Symbol(3); // 多次赋值不支持 ❌ Uncaught TypeError: Assignment to constant variable.
const a81; // 空值声明不支持 ❌ Uncaught SyntaxError: Missing initializer in const declaration
数据类型判断
typeof
只能识别基础类型和引用类型
js
// 基本类型
console.log(typeof NaN); // "number"
console.log(typeof true); // "boolean"
console.log(typeof Symbol()); // "symbol"
console.log(typeof BigInt(1)); // "bigint"
console.log(typeof ""); // "string"
console.log(typeof undefined); // "undefined"
// 基本类型的特殊类型
// 在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。
// 对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),
// 因此,null 的类型标签是 0,typeof null 也因此返回 "object"。
console.log(typeof null); // "object"
// 引用类型 object
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof document.body); // "object"
// 引用类型 function
console.log(typeof class {}); // "function"
console.log(typeof function () {}); // "function"
// 基本类型
console.log(typeof NaN); // "number"
console.log(typeof true); // "boolean"
console.log(typeof Symbol()); // "symbol"
console.log(typeof BigInt(1)); // "bigint"
console.log(typeof ""); // "string"
console.log(typeof undefined); // "undefined"
// 基本类型的特殊类型
// 在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。
// 对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),
// 因此,null 的类型标签是 0,typeof null 也因此返回 "object"。
console.log(typeof null); // "object"
// 引用类型 object
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof document.body); // "object"
// 引用类型 function
console.log(typeof class {}); // "function"
console.log(typeof function () {}); // "function"
constructor
constructor 指向创建该实例对象的构造函数
js
const arr = [1, 2, 3];
console.log(arr.constructor === Array); // true
const obj = { name: "云牧", age: 18 };
console.log(obj.constructor === Object); // true
String.prototype.constructor = function fn() {
return {}; // constructor 可以被改写
};
console.log("云牧".constructor); // [Function: fn]
const arr = [1, 2, 3];
console.log(arr.constructor === Array); // true
const obj = { name: "云牧", age: 18 };
console.log(obj.constructor === Object); // true
String.prototype.constructor = function fn() {
return {}; // constructor 可以被改写
};
console.log("云牧".constructor); // [Function: fn]
instanceof
语法:obj instanceof Type
- 功能:判断 obj 是不是 Type 类的实例,只可用来判断引用数据, 右操作数必须是函数或者 class
- 实现:Type 的原型对象是否是 obj 的原型链上的某个对象
js
// 引用对象
const arr = [1, 2, 3];
console.log(arr instanceof Array); // true
console.log(arr instanceof Object); // true
// 基本类型
console.log(Number(123) instanceof Number); // false
console.log(123 instanceof Number); // false
// Object
console.log(new Number(123) instanceof Number); // true
console.log(Number instanceof Object); // true
// 引用对象
const arr = [1, 2, 3];
console.log(arr instanceof Array); // true
console.log(arr instanceof Object); // true
// 基本类型
console.log(Number(123) instanceof Number); // false
console.log(123 instanceof Number); // false
// Object
console.log(new Number(123) instanceof Number); // true
console.log(Number instanceof Object); // true
isXXX
Array.isArray(value)
静态方法用于确定传递的值是否是一个 Array。isNaN(value)
函数用来确定一个值是否为 NaN (参数隐式转换数值)。Number.isNaN(value)
不会尝试将参数转换为数字,因此非数字总是返回 false。isFinite(value)
函数用来判断被传入的参数值是否为一个有限数值 (参数隐式转换数值)Number.isFinite(value)
只有类型为数字且为有限数的值才返回 true。Object.prototype.isPrototypeOf(object)
判断一个对象是否为另一个对象的直接原型
Reflect.toString.call(value)
等同于 Object.prototype.toString.call(value)
js
var a = null;
console.log(Reflect.toString.call(a)); // '[object Null]'
console.log(Object.prototype.toString.call(a)); // '[object Null]'
var a = null;
console.log(Reflect.toString.call(a)); // '[object Null]'
console.log(Object.prototype.toString.call(a)); // '[object Null]'
手写判型
js
function isPromise(value) {
const isFn = (val) => typeof val === "function";
const isPromise = isObject(value) && isFn(value.then) && isFn(value.catch);
return value instanceof Promise || isLikePromise;
}
function isUndefined(obj) {
// void 0 始终返回 undefined,void 后面接任意值都是返回 undefined,
// 这是为了兼容 IE,因为在 IE 中 undefined 值可以被改写
return obj === void 0;
}
function isPromise(value) {
const isFn = (val) => typeof val === "function";
const isPromise = isObject(value) && isFn(value.then) && isFn(value.catch);
return value instanceof Promise || isLikePromise;
}
function isUndefined(obj) {
// void 0 始终返回 undefined,void 后面接任意值都是返回 undefined,
// 这是为了兼容 IE,因为在 IE 中 undefined 值可以被改写
return obj === void 0;
}