
开始之前,先了解一些基本背景...
我们知道,在 ECMAScript 标准中,当前数据类型分为两类(共 8 种):
- 原始类型(Primitives): 包含 Undefined、Null、Boolean、String、Number、Symbol、BigInt 共 7 种基本数据类型。
- 引用类型(Objects):除原始类型之外,其余均属于引用类型,归为一大类,比如
Object、Array、Map等内置方法及其实例对象。
其中,原始值都是不可改变的,且不含任何属性或方法。平时看到类似的 'string'.length 写法,本质上是发生了隐式类型转换,先将 'string' 转换为 Object('string'),然后调用 String 实例对象的 length 属性罢了。
下面,我们将「引用类型」划分为两类:
函数对象(function object):一个具有
[[Call]]内部方法(详见)的对象,简单来说,就是可以通过()调用的对象,比如内置的Object、Function、Array等方法。
普通对象(ordinary object):除函数对象,其余引用值均可称为普通对象。
注意,这里提到的对象泛指引用类型,而不是单指平常所写的 {...} 对象。请记住:
所有
Function的实例都是函数对象,而其他的都是普通对象。
前面划分对象,就是为了方便分清楚 prototype(原型对象)和 __proto__ (原型)的区别:
| 对象类型 | prototype | __proto__ |
|---|---|---|
| 普通对象 | ❌ | ✅ |
| 函数对象 | ✅ | ✅ |
换句话说:
所有对象都有
__proto__属性,而只有函数对象才具有prototype属性。
不作过多介绍,如果对这俩兄弟不太了解的,可看文章数据类型详解。
从 MDN 可知,其语法非常简单:
object instanceof constructor
用于检测 constructor.prototype 是否存在于参数 object 的原型链上。
要自实现 instanceof,就要了解这些特性:
object必须是引用值,否则将会返回false。constructor必须是函数对象,否则会抛出 TypeError。
需要注意的是:不同上下文(比如网页中多个 <iframe>)之间拥有不同的全局对象,可理解为不同的引用地址,因此会出现如下情况:
const iframe = document.createElement('iframe')
document.body.appendChild(iframe)
const xArray = window.frames[window.frames.length - 1].Array
const xarr = new xArray()
const arr = new Array()
console.log(xarr instanceof Array) // false
console.log(xarr.constructor === Array) // false
console.log(arr instanceof Array) // true
console.log(arr.constructor === Array) // true
因此,使用 instanceof 来判断是否为数组是不准确的,可看文章。
获取原型对象的方法:
// 构造函数访问 prototype 属性
constructor.prototype
// 实例对象访问 __proto__ 属性
instance.__proto__
// __proto__ 非 ECMAScript 标准,只是被所有浏览器支持罢了
// 可使用标准中的 Object.getPrototypeOf() 方法替换
实现如下:
function myInstanceof(inst, ctor) {
// 是否为函数对象
const isCallable = val => typeof val === 'function'
// 是否为引用值
const isObject = val => typeof val === 'function' || (val !== null && typeof val === 'object')
// ctor 必须是引用值
if (!isObject(ctor)) throw new TypeError(`Right-hand side of 'instanceof' is not an object`)
// ctor 必须是函数对象
if (!isCallable(ctor)) throw new TypeError(`Right-hand side of 'instanceof' is not callable`)
// inst 为原始值,则返回 false
if (!isObject(inst)) return false
do {
const proto = inst.__proto__ // 可换成标准方法 const proto = Object.getPrototypeOf(inst)
// 原型链顶端(proto 为 null)或者 inst 通过 Object.create(null) 构造(proto 为 undefined)
if (proto == null) return false
if (proto === ctor.prototype) return true
inst = proto // 往上一级查找
} while (true)
}
The end.
我希望我的React.js应用程序中的类可以从.styl文件中导出,就像从CSS模块中导出一样,但我找不到任何类这个问题的现成解决方案。我找到了aguidetosettingupCSSModules在使用CreateReactApp创建的应用程序中。我知道您需要运行npmruneject并以某种方式重写配置文件,但如何——我不明白。 最佳答案 您需要在项目中安装下一个npm-packages:stylusstylus-loadercss-loader在webpack.config中,在module部分你需要添加以下几点:{test:
当在构造函数上设置原型(prototype)时,instanceof运算符仅返回true,直到原型(prototype)被更改。为什么?functionSomeConstructorFunction(){}functionextendAndInstantiate(constructorFn){constructorFn.prototype={};//CanbeanyprototypereturnnewconstructorFn();}varchild1=extendAndInstantiate(SomeConstructorFunction);console.log(child1ins
这两种说法有什么区别?它们给出不同的输出(在googlechrome控制台中)。functionTest(){if(thisinstanceofTest){}else{returnnewTest();}}x=Test();测试{}functionTest(){if(!thisinstanceofTest){returnnewTest();}}x=Test();未定义头脑=困惑 最佳答案 问题是!在instanceof之前计算,因此它被视为:if((!this)instanceofTest){...}而且,无论!this是true还是
这article定义instanceof如下:Theinstanceofoperatortestswhetheranobjecthasinitsprototypechaintheprototypepropertyofaconstructor.这是一个公平的解释,在我从EloquentJavascript书中看到这段代码之前,生活一直很美好:functionTextCell(text){this.text=text.split("\n");}TextCell.prototype.minWidth=function(){returnthis.text.reduce(function(wid
functionFoo(){}functionBar(){}Bar.prototype=newFoo()console.log("Bar.prototype.constructor===Foo?"+(Bar.prototype.constructor===Foo))console.log("newBar()instanceofBar?"+(newBar()instanceofBar))=>Bar.prototype.constructor===Foo?true=>newBar()instanceofBar?true为什么“instanceof”的结果不是“false”,因为“const
考虑以下ES6类:'usestrict';classDummy{}classExtendDummyextendsDummy{constructor(...args){super(...args)}}classExtendStringextendsString{constructor(...args){super(...args)}}consted=newExtendDummy('dummy');constes=newExtendString('string');console.log(edinstanceofExtendDummy);console.log(esinstanceofEx
我正在构建一个涉及继承和使用instanceofjavascript关键字的BackboneJS应用程序。我有以下代码:app.Sport=Backbone.Model.extend({defaults:{id:0,title:'Running'}});在代码的后面,我通过键入来实例化一个新的Sport:varnewSport=newapp.Sport();我可以毫无问题地操作这个新创建的实例。但是,因为有一个但是,instanceof关键字在询问我的实例类型时总是返回false:console.log('isnewSportaSportinstance?'+newSportinsta
我在javascript中使用instanceof时偶然发现了以下内容。ArrayinstanceofObjectreturnstrueObjectinstanceofArrayreturnsfalse这里Array和Object是什么关系? 最佳答案 在构造函数之间,关系或prototypechain是:Array->Function.prototype->Object.prototypeObject->Function.prototype->Object.prototype第一个是true因为构造函数是一个Function而函数
如果我错了,请原谅我,但我认为这样做:functionMyObject(){return{key:'value',hello:function(){console.log('world');}};}varobj=newMyObject();我创建了一个MyObject类型的新实例。但是,如果我这样做:objinstanceofMyObject它返回false。这让我感到困惑,因为我认为这会返回true。我在这里做错了什么?这是一个fiddle测试这个。我以为我掌握了JavaScript的基础知识,但也许不是。但是,我找到了sources这与我的发现相矛盾。
instanceof运算符应该看看原型(prototype),不是吗?为什么在更改对象的原型(prototype)后它不更改答案?示例如下://The.prototypeofobjectscreatedwith'newMyKlass'//isMyKlass.prototypevarMyKlass=function(name,age){this.name=name;this.age=age;}varxx=newMyKlass('xx',20);console.log(xxinstanceofMyKlass);//true,OKxx.prototype=newString('s');con