原型、原型链、instanceof、isprototypeof详解

主要弄清楚这几个概念:

  1. 继承(原型、原型链、prototype、proto、new)
  2. instanceof 和 isprototypeof的区别

1. 概念

1.1 javascript 继承的来源

总是记不住javascript的prototype继承原理和原因,脑子容易混沌。查看阮一峰的文章后,自己总结如下:

  • 刚开始需要一个脚本语言,不需要复杂。
  • 当时java很流行,java使用了object对象。于是决定使用object对象。
  • c++和java都有new来创建对象,javascript也引用了new,
  • 但是简化了new,javascript中new的对象是构造函数,也就是一个函数。
  • 但是new有一个缺点就是无法共享数据,于是prototype出来了,这样私有数据在构造函数中,共享数据在prototype中。
function  dog(name){
  this.name = name
}

dog.prototype = {
  type:"animate"
}

var a = new dog('gou')
var b = new dog('mao')
dog.prototype.type = 'dongwu';

console.log(a.name); // gou
console.log(b.name); // mao
console.log(a.type); // dongwu
console.log(b.type); // dongwu

1.2 原型链概念

少不得要放这张图片(^_^)
JavaScript 原型链

下面是我理解的概念:原概念可以看这里

  1. 实例对象有__proto__属性(指向构造函数的原型对象)
  2. 函数有prototype属性
  3. 函数的prototype是对象类型
  4. __proto__属性指向函数的原型对象,prototype就是函数的原型对象
  5. Object.__proto__ === Function.__proto__ === foo.__proto__ === Function.prototype

我理解的原型链:

  javascript一切皆对象,每个实例对象都有__proto__属性,指向它构造函数的实例对象(prototype),而实例对象又是一个对象,所以又拥有了__proto__属性,直到null为止,这就是原型链的生成。
  ps:为什么使用__proto_属性,可以参考本文下方的new的实现。_

光概念不行,还要有两个栗子:

Function.prototype.a = 'Function'
Object.prototype.a = 'Object'
function foo(name){
    
    }
var a = new foo();
console.log(a.a) // Object

// 原型链从__proto__开始查找, 
// 步骤:foo.__proto__ ---> foo.prototype ---> Object.prototype
// 结果: Object, 根本未经历Function.prototype
function foo(){
    
    }
var a = new foo();
console.log(a.__proto__ === foo.prototype); // true, proto指向声明它的原型的prototype
console.log(foo.__proto__ === Function.prototype) // true, function声明变量的proto指向Function.prototype
console.log(Function.prototype.__proto__ === Object.prototype); // true, prototype也有proto,指向Object的prototype
console.log(Object.prototype.__proto__ === null); //true, Object的prototype的proto指向null

ps:最好去权威的网站看一些原始的概念,这样会更好。


3.instanceof

A instanceof B
说法1:B 构造函数的prototype对象是否在A的原型链上
说法2:A对象是否是B对象的实例
说法3:B对象是否是A对象的父对象
我觉得说法2还是最合适的

伪代码:

function instanceof(left,right){
    
    
    while(true){
    
    
        if(left.__proto__ === null){
    
    
            return false;
        }

        if(left.__proto__ === right.prototype){
    
    
            return true;
        }

        left = left.__proto__;
    }
}

易错小栗子:

var simpleStr = "This is a simple string"; 
var myString  = new String();
var newStr    = new String("String created with constructor");

simpleStr instanceof String; // 返回 false, 检查原型链会找到 undefined
myString  instanceof String; // 返回 true
newStr    instanceof String; // 返回 true
myString  instanceof Object; // 返回 true

Object.create(null) instanceof Object // false, 创建了一个原型为null的空对象,检查原型链会找到 undefined

易错小栗子二:和isprototypeof的区别(答案全部是true)

var fn = function(){
    this.nick = 'nick'
    this.age = '18'
}

fn.prototype.getNick = function(){
    console.log(this.nick)
}

fn.hello = function(){
    console.log('hello')
}

fn.getAge = function(){
    console.log(this.hello())
    return '1'
}

var sub = function(){

}

sub.prototype = Object.create(fn.prototype)
sub.prototype.constructor = sub;

var sb = new sub();

console.log(sb instanceof fn)
console.log(fn.prototype.isPrototypeOf(sb))


var c = Object.create(fn.prototype)

console.log(c instanceof fn)
console.log(fn.prototype.isPrototypeOf(c))


var obj = {
    a:'a'
}

var t = Object.create(obj)

console.log(t instanceof Object)
console.log(Object.prototype.isPrototypeOf(t))

4. isprototypeof

A.isPrototypeOf(B):
B对象是否在A的原型链上

var o={
    
    };
function Person(){
    
    };
var p1 =new Person();//继承自原来的原型,但是现在已经无法访问
Person.prototype=o;
var p2 =new Person();//继承自o
console.log(o.isPrototypeOf(p1));//false o不是p1的原型
console.log(o.isPrototypeOf(p2));//true o是p2的原型

// 这个栗子来源于网上,我稍微修改了一下。我认为这个栗子并不好,  
// 因为实际使用一般是o.prototype.isPrototypeOf(p2),而非o.isPrototypeOf(p2)

5. instanceof和isprototypeof的区别

我认为就是参数的区别
不是参数的区别,是后者检测的更全面(可以对constructor检测)
就是参数的区别
object instanceof constrouctor
prototypeObject.isPrototypeOf(Object)

6. new

引用自:地址

function myNew(){
    
    
	var constructor = [].shift.call(arguments); //注意是shift,不是slice
	var obj = new Object();
	obj.__proto__ = constructor.prototype;
	constructor.apply(obj,arugments)
	return obj;
}

猜你喜欢

转载自blog.csdn.net/a519991963/article/details/95505746