发表日期: 2021-06-16 09:57:59 浏览次数:177
【网站建设】北京网站制作-北京网络公司-北京网页设计-北京网店美工-北京网站开发
北京(Beijing),简称“京”,古称燕京、北平,是中华人民共和国的首都、直辖市、国家中心城市、超大城市,国务院批复确定的中国政治中心、文化中心、国际交往中心、科技创新中心 [1] ,截至2020年,全市下辖16个区,总面积16410.54平方千米,常住人口2189.31万人 [129] 。城镇人口1865万人,城镇化率86.6%(2018年末数据) [2] ,常住外来人口达794.3万人(2017年数据) [3] 。北京地处中国北部、华北平原北部,东与天津毗连,其余均与河北相邻,中心位置东经116°20′、北纬39°56′,是世界著名古都和现代化国际城市,也是中国共产党中央委员会、中华人民共和国中央人民政府和全国人民代表大会常务委员会的办公所在地 [4] 。
北京地势西北高、东南低。西部、北部和东北部三面环山,东南部是一片缓缓向渤海倾斜的平原。境内流经的主要河流有:永定河、潮白河、北运河、拒马河等,多由西北部山地发源,穿过崇山峻岭,向东南蜿蜒流经平原地区,最后分别汇入渤海。北京的气候为暖温带半湿润半干旱季风气候,夏季高温多雨,冬季寒冷干燥,春、秋短促 [5-6] 。
北京被世界城市研究机构GaWC评为世界一线城市 [7] ,联合国报告指出北京人类发展指数居中国城市第二位, [8] 2020年,北京市全年实现地区生产总值36102.6亿元,按可比价格计算,比上年增长1.2% [9] 。
JavaScript 的数据类型包括原始类型和对象类型:
原始类型:Null
、Undefined
、Number
、String
、Boolean
、Symbol
、BigInt
对象类型:Object
我们习惯把对象称为引用类型,当然还有很多特殊的引用类型,比如 Function
、Array
、RegExp
、Math
、Date
、Error
、Set
、Map
、各种定型数组 TypedArray
等。
原始类型值保存在栈中,对象类型值保存在堆中,在栈中保留了对象的引用地址,当 JavaScript 访问数据的时候,通过栈中的引用访问。
在 JavaScript 中,原始类型的赋值会完整复制变量值,而对象(引用)类型的赋值是复制引用地址。
let a = { name: '前端博客', age: 2 } let b = a console.log(a.name) b.name = '码云笔记' console.log(a.name) console.log(b.name) // 前端博客 // 码云笔记 // 码云笔记
第一题 So Easy,闭着眼睛也能答对。
let a = { name: '前端博客', age: 2 } const expand = function(b) { b.age = 18 b = { name: '码云笔记', age: 25 } return b } let c = expand(a) console.log(c.age) console.log(a.age) console.log(a) // 25 // 18 // {name: "前端博客", age: 18}
这道题可能有些同学会答错,我们来一起分析一下:
expand
函数传进来的参数 b
,其实传递的是对象在堆中的内存地址值,通过调用 b.age = 18
可以改变 a
对象的 age
属性。
但是 return
又把 b
变成了另一个内存地址,将 {name: "码云笔记", age: 25}
存入,导致最后返回 a 的值就变成了 {name: "码云笔记", age: 25}
我会问你一些问题,你随时可以喝水。
JavaScript 中检测数据类型的方法你知道吗?
typeof
instanceof
constructor
Object.prototype.toString.call()
那 typeof
用起来怎么样呢?
typeof 'a' // 'string' typeof 1 // 'number' typeof true // 'boolean' typeof undefined // 'undefined' typeof Symbol('a') // 'symbol' typeof 1n // 'bigint' typeof null // 'object' typeof function() {} // 'function' typeof [] // 'object' typeof {} // 'object' typeof /a/ // 'object' typeof new Date() // 'object' typeof new Error() // 'object' typeof new Map() // 'object' typeof new Set() // 'object'
两条结论:
typeof 可以判断除了 null 以外的原始类型。
typeof 只能判断对象类型中的 Function,其他判断不出来,都为 object。
typeof
检测 null
时返回 object
,是最初 JavaScript 语言的一个 Bug,为了兼容老代码一直保留至今。
如果想了解更多,请戳下面链接。链接
这里不得不提一下 NaN
,毕竟我们都知道它戏比较多。
typeof NaN // number
F**k NaN!
instanceof
能判断出哪些类型你知道吗?
检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
也就是使用 a instanceof B
判断的是:a 是否为 B 的实例,即 a 的原型链上是否存在 B 的构造函数。
console.log(1 instanceof Number) // false console.log(new Number(1) instanceof Number) // true const arr = [] console.log(arr instanceof Array) // true console.log(arr instanceof Object) // true const Fn = function() { this.name = '构造函数' } Fn.prototype = Object.create(Array.prototype) let a = new Fn() console.log(a instanceof Array) // true
两条结论:
instanceof
可以准确判断对象(引用)类型,但是不能准确检测原始类型。
由于我们可以随意修改原型的指向导致检测结果不准确,所以这种方法是不安全的。
如果我就想用 instanceof
检测原始类型,你能满足我的需求吗?
好,满足。
虽然 instanceof
不能检测原始类型,但是有一种方法可以让其用于检测原始类型。
Symbol.hasInstance
允许我们自定义 instanceof
的行为。
class PrimitiveNumber { static [Symbol.hasInstance] = x => typeof x === 'number'; } 123 instanceof PrimitiveNumber; // true class PrimitiveString { static [Symbol.hasInstance] = x => typeof x === 'string'; } 'abc' instanceof PrimitiveString; // true class PrimitiveBoolean { static [Symbol.hasInstance] = x => typeof x === 'boolean'; } false instanceof PrimitiveBoolean; // true class PrimitiveSymbol { static [Symbol.hasInstance] = x => typeof x === 'symbol'; } Symbol.iterator instanceof PrimitiveSymbol; // true class PrimitiveNull { static [Symbol.hasInstance] = x => x === null; } null instanceof PrimitiveNull; // true class PrimitiveUndefined { static [Symbol.hasInstance] = x => x === undefined; } undefined instanceof PrimitiveUndefined; // true
既然你对 instanceof
这么了解了,能给我现场手写一个吗?
const myInstanceof = function(left, right) { if (typeof left !== 'object' || left === null) return false let proto = Reflect.getPrototypeOf(left) while (true) { if (proto === null) return false if (proto === right.prototype) return true proto = Reflect.getPrototypeOf(proto) } } const arr = [] console.log(myInstanceof(arr, Array)) // true console.log(myInstanceof(arr, Object)) // true console.log(myInstanceof(arr, RegExp)) // false
要理解 instanceof 的工作原理,就必须理解原型链,对 JavaScript 原型链掌握的不够深刻的同学可以戳下面链接学习。
我对js中原型原型链的理解(有图有真相)
第五篇 谈谈你对原型链的理解
constructor
怎么样,好用吗?
对于数值直接量,直接使用 constructor
是会报错的,这个错误来自于浮点数的字面量解析过程,而不是 “.” 作为存取运算符的处理过程。
在 JS 中,浮点数的小数位是可以为空的,因此 1. 和 1.0 会解析成相同的浮点数。
// 所以需要加上一个小括号,小括号运算符能够把数值转换为对象 (1).constructor // ƒ Number() { [native code] } // 或者 1..constructor // ƒ Number() { [native code] } const a = '前端食堂' console.log(a.constructor) // ƒ String() { [native code] } console.log(a.constructor === String) // true const b = 5 console.log(b.constructor) // ƒ Number() { [native code] } console.log(b.constructor === Number) // true const c = true console.log(c.constructor) // ƒ Boolean() { [native code] } console.log(c.constructor === Boolean) // true const d = [] console.log(d.constructor) // ƒ Array() { [native code] } console.log(d.constructor === Array) // true const e = {} console.log(e.constructor) // ƒ Object() { [native code] } console.log(e.constructor === Object) // true const f = () => 1 console.log(f.constructor) // ƒ Function() { [native code] } console.log(f.constructor === Function) // true const g = Symbol('1') console.log(g.constructor) // ƒ Symbol() { [native code] } console.log(g.constructor === Symbol) // true const h = new Date() console.log(h.constructor) // ƒ Date() { [native code] } console.log(h.constructor === Date) // true const i = 11n console.log(i.constructor) // ƒ BigInt() { [native code] } console.log(i.constructor === BigInt) // true const j = /a/ console.log(j.constructor) // ƒ RegExp() { [native code] } console.log(j.constructor === RegExp) // true String.prototype.constructor = 'aaa' console.log(a.constructor === String) // false const k = null console.log(k.constructor) // Cannot read property 'constructor' of null const l = undefined console.log(l.constructor) // Cannot read property 'constructor' of undefined
两条结论:
除了 null 和 undefined,constructor
可以正确检测出原始类型和对象(引用)类型。
由于我们可以随意修改 constructor
导致检测结果不准确,所以这种方法是不安全的。
还剩下 Object.prototype.toString
了,它就无懈可击了吗?
toString()
方法返回一个表示该对象的字符串,我们可以改变它的 this 指向,将 this 指向要检测的值,即可返回当前检测值的信息。
Object.prototype.toString({}) // '[object Object]' Object.prototype.toString.call({}) // '[object Object]' Object.prototype.toString.call('a') // '[object String]' Object.prototype.toString.call(1) // '[object Number]' Object.prototype.toString.call(true) // '[object Boolean]' Object.prototype.toString.call(null) // '[object Null]' Object.prototype.toString.call(undefined) // '[object Undefined]' Object.prototype.toString.call(Symbol('a')) // '[object Symbol]' Object.prototype.toString.call(11n) // '[object BigInt]' Object.prototype.toString.call(/a/) // '[object RegExp]' Object.prototype.toString.call(new Date()) // '[object Date]' Object.prototype.toString.call([0, 1, 2]) // '[object Array]' Object.prototype.toString.call(function() {}) // '[object Function]' Object.prototype.toString.call(new Error()) // '[object Error]' Object.prototype.toString.call(new Set()) // '[object Set]' Object.prototype.toString.call(new Map()) // '[object Map]'
你能封装一个检测数据类型的通用方法吗?
封装方法的时候注意大小写。
方案有很多种,这里简单提供两个思路。
const getType = function(obj) { let type = typeof obj if (type !== 'object') { return type } return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1').toLowerCase() } getType({}) // object getType('a') // string getType(1) // number getType(true) // boolean getType(null) // null getType(undefined) // undefined getType(Symbol('a')) // symbol getType(11n) // bigint getType(/a/) // regexp getType(new Date()) // date getType([0, 1, 2]) // array getType(function() {}) // function getType(new Error()) // error getType(new Map()) // map getType(new Set()) // set
当然,换个姿势,这样也可以实现。
Object.prototype.toString.call('1').slice(8, -1).toLowerCase() // 'string'
聊到这,基本上就是满分答案了。
备案号: 苏ICP备11067224号
CopyRight © 2011 书生商友信息科技 All Right Reserved
24小时服务热线:400-111-6878 E-MAIL:1120768800@qq.com QQ:1120768800
网址: https://www.768800.com 网站建设:上往建站
关键词: 网站建设| 域名邮箱| 服务器空间| 网站推广| 上往建站| 网站制作| 网站设计| 域名注册| 网络营销| 网站维护|
企业邮箱| 虚拟主机| 网络建站| 网站服务| 网页设计| 网店美工设计| 网站定制| 企业建站| 网站设计制作| 网页制作公司|
400电话办理| 书生商友软件| 葬花网| 调温纤维| 海洋馆运营维护| 北京保安公司| 殡仪馆服务| 殡葬服务| 昌平殡葬| 朝阳殡葬|
欢迎您免费咨询,请填写以下信息,我们收到后会尽快与您联系
服务热线:400-111-6878