You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// Function 实例functionfn1(){}varfn2=function(){}varfn3=newFunction('console.log("Hi, everyone")')// 一般不使用 Function 构造器去生成 Function 对象,相比函数声明或者函数表达式,它表现更为低效。// Object 实例varobj1={}varobj2=newObject()varobj3=newfn1()
varobj=Object.create(null)varobj1=Object.create(null)varobj2={}obj.__proto__===undefined// trueobj.getPrototypeOf()// 抛出错误 TypeError: obj.getPrototypeOf is not a function
今天又又又...又整理了一下,那些 JavaScript 里不清不楚的知识点。
一、数据类型的分类
截止发文日期,ECMAScript 标准的数据类型仅有 8 种(ECMAScript Language Types)。可以分为两类:
typeof(instance) === 'object'
)typeof(instance) === 'symbol'
)typeof(instance) === 'bigint'
)原始类型的比较的是值,只有两者的值相等,那么它们被认为是相等的,否则不相等。而引用类型比较的是地址,当两者的标识符同时指向内存的同一个地址,则被认为是相等的,否则不相等。
二、原始类型与原始值
所有基本类型的值(即原始值,Primitive Values)都是不可改变(immutable)的,而且不含任何属性和方法的。
到这里可能会有小伙伴打问号了???
Q1:原始类型与原始值有什么区别?
Q2:原始值不可改变?这样不是改变了吗?
基本类型值可以被替换,但不能被改变。
再有示例:
Q3:原始值没有任何属性和方法?那这个是怎么回事?
在 JavaScript 中除了
null
和undefined
之外,所有的基本类型都有其对应的包装对象(Wrapper Object)。因此,访问null
或undefined
的任何属性和方法都会抛出错误。String
为字符串基本类型。Number
为数值基本类型。BigInt
为大整数基本类型。Boolean
为布尔基本类型。Symbol
为字面量基本类型。这些包装对象的
valueOf
方法返回其对应的原始值。不是说好的,原始值不含任何的属性和方法吗?那
foo.length
和foo.toUpperCase()
是咋回事啊???其实它内部是这样实现的:当字符串字面量调用一个字符串对象才有的方法或属性时,JavaScript 会自动将基本字符串转化为字符串对象并且调用相应的方法或属性。(Boolean 和 Number 也同样如此)。
我们尝试在控制台上打印一下
new String('foo')
,可以看到该实例对象有一个length
属性,其值为3
,实例对象本身没有toUpperCase()
方法,所以接着往原型上查找,果然找到了。(由于原型上方法太多,截图里没有展开,否则影响文章篇幅)因此
可下面为什么
length
还是3
呢?三、对象
在 JavaScript 中,除了以上的原始值,其余都属于对象。
与原始类型不同的是,对象是可变(mutable)的。
1. 对象的分类
我们可以将对象划分为普通对象(ordinary object)和函数对象(function object)。
那怎样区分呢?我们先定义一些
Function
实例和Object
实例:我们来打印一下结果:
Object
和Function
本身就是 JavaScript 中自带的函数对象。其中obj1
、obj2
、obj3
为普通对象(均为Object
的实例),而fn1
、fn2
、fn3
为函数对象(均是Function
的实例)。记住以下这句话:
2. 对象的原型
接着,引入两个很容易让人抓狂、混淆的两兄弟
prototype
(原型对象)和__proto__
(原型)。这俩兄弟的主要是为了构造原型链而存在的。因此有以下结论:
再上几个菜,请慢慢品尝:
在 JavaScript 中访问一个对象属性,它在原型上是怎样查找的呢?
我们可以在控制台打印一下,看下两者的区别。
JavaScript 常被描述为一种基于原型的语言 —— 每个对象拥有一个原型(
[[Prototype]]
),对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链(prototype chain)。3. 继承
关于继承内容,可看另外一篇文章:深入 JavaScript 继承原理。
4. 对象的内部属性(Internal properties)
在规范中,对象的内部方法和内部插槽使用双方括号
[[]]
中包含的名称标识,且首字母为大写。例如[[Prototype]]
、[[Class]]
、[[Extensible]]
、[[Call]]
、[[Scopes]]
、[[FunctionLocation]]
等等。下面挑几个来讲一下:
4.1 [[Class]]
[[Class]]
是对象的一个内部属性,其值为以下字符串之一:Function
、Object
、Array
、Boolean
、Number
、String
、Symbol
、RegExp
、JSON
、Date
、Math
、Error
、Arguments
等。BigInt
、Set
、WeakSet
、Map
、WeakMap
、Reflect
、Promise
、GeneratorFunction
、AsyncFunction
、Window
、Intl
、WebAssembly
,以及派生于HTMLElement
的(如HTMLScriptElement
)等等。我们都知道
typeof
无法判断对象的具体类型,无论是typeof {}
、typeof []
、还是typeof Math
都返回"object"
。但有了[[Class]]
属性之后,我们就可以利用它来判断对象的类型了。访问[[Class]]
的唯一方法是通过默认的toString()
方法(该方法是通用的):以下封装了获取对象类型的方法:
4.2 [[Construct]]
一个对象里,如若没有
[[construct]]
属性,是无法使用new
关键字进行构造的。四、类型转换
在 JavaScript 中,我们会经常使用相等运算符(
==
)去比较两个操作数是否相等。当两个操作数一个是引用类型,另一个是原始类型的时候,前者会先转换为原始类型,再比较。那么,引用类型是如何转换为原始类型的呢?
未完待续...
参考
The text was updated successfully, but these errors were encountered: