原型和原型链、类型判断
js原型的出现
1.构造函数
js设计之初,是作为提供网络交互的简易脚本语言,设计者并未想设计类,但需要有一种机制将所有对象联系起来,设计者借用了new关键字,但后边跟的并不是类名,而是直接的构造函数
function test(){ // 实际上这样就定义了一个构造函数
this.name = "test"
}
let x = new test() // new对象后边跟的是构造函数
2.prototype
但是这样出现的问题是:无法共享属性,即每个对象都会有自己的属性和方法,无法提取共同部分进行复用,因此js设计者提出用prototype的方式,将需要共享的属性方法放在prototype中,不需要共享的则放在构造函数。
大概的思路是:我没必要单独搞一个类出来,但是只要我想我就可以共用一些东西
function dog(name){
this.name = name;
}
dog.prototype.getName = function(){
console.log(this.name);
}
let dog1 = new dog("哈士奇");
3.原型链
因此新建的对象由两个部分组成自己的属性和对应prototype的属性,而对应prototype的属性即为每个对象都用于的__ proto _ _, 他指向构造函数的prototype,即dog1. __ proto _ _ == dog.prototype
由于dog.prototype本身也是由构造函数new出来的,所以他本身作为一个对象也会有__ proto _ ,同时其内部有一个constructor属性,指向构造函数,构造函数的 __ proto __ 指向function.prototype
并且原型链是指对象的原型链,原型链上所有节点都是对象,不能是基本值,所以最后的节点应该为null,玄学一点的说法是所有事情都是从无到有(手动狗头)
即有两条原型链
(1)
dog.prototype._ _ proto_ _ _ == Object.prototype Object.prototype._ _ proto_ _ = null
(2)
dog.prototype.constructor._ _ proto_ _ == Function.prototype Function.prototype._ _ proto_ _ = Object.prototype Object.prototype._ _ proto_ _ = null
js类型判断
type of
可以利用 typeof
来判断number
, string
,object
, boolean
, function
, undefined
, symbol
这七种类型,
但type of并不能够直接判断出这个数据具体是那种object,以下是原理:
- 000:对象
- 010:浮点数
- 100:字符串
- 110:布尔
- 1:整数
but, 对于 undefined
和 null
来说,这两个值的信息存储是有点特殊的。
null
:所有机器码均为0
undefined
:用 −2^30 整数来表示
因此 null在被判断时就会被判断为对象,
所以当我们使用typeof时最好用他来判断基本类型,避免对null的判断
instance of
instanceof
主要的作用就是判断一个实例是否属于某种类型,也可以判断一个实例是否是其父类或者祖先类的实例。
以下为大概的代码思路:
function test_Instance(leftValue,rightValue){
let right = rightValue.prototype;
let left = leftValue.__proto__;
while(true){
if(left == null){
return false;
}
if(left == right){
return true;
}
left = left.__proto__;// 向上查找对象的__proto__属性,
}
}
判断当前所在层级的原型是否为要判断的原型,如果不是,则向上查找,进行遍历,如果是,则返回true
比较好的办法;
以下为较为准确的办法:
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('hi') // "[object String]"
Object.prototype.toString.call({a:'hi'}) // "[object Object]"
Object.prototype.toString.call([1,'a']) // "[object Array]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(() => {}) // "[object Function]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(Symbol(1)) // "[object Symbol]"
根据原型链向上查找
参考文章:
-
Javascript继承机制的设计思想:www.ruanyifeng.com/blog/2011/0…
-
浅谈 instanceof 和 typeof 的实现原理https://juejin.cn/post/6844903613584654344#heading-0