javaScript原型链

掌握原型属性、构造函数的prototype属性、实例的__proto__([[prototype]],这是个内置属性,可以通过Object.setPrototypeOf(obj, proto)和Object.getPrototypeOf(obj)设置或获取该属性的值,也可以通过__proto__代替[[prototype]]进行操作)属性、new操作符之间的关系,以及原型链的概念,那么就可以掌握原型链这个知识点。

注意JS各构造函数之间的关系;基本所有对象实例都继承于Object,Object.prototype处于原型链的顶端;

//JS中的原型链是指对象实例上的原型链(原型的原型的原型,就这样一层一层向上访问,形成一条链),
//一般如下表示,直到最后访问到的原型对象是null为止
//obj.__proto__.__proto__.__proto__....

//JS原型的作用,属性块级化和代码复用,它有个特性就是对象实例找不到的属性可以
//往上找它的原型对象上的属性
//原型对象找不到的就继续在原型对象的原型对象上的属性,依次这样递归寻找;
//直到找到或最后的原型对象是null为止;
//这样的特性,当原型链上有多个同属性名存在,在后面的往往会被屏蔽即后面的无法在原型链上被访问。

//对象实例上的原型对象是怎么来的??每个对象都是各自具体构造函数的实例。
//注意,每个构造函数都有自己的prototype对象,这个对象实际上是各自构造函数的实例的原型的依据;
//即实例的原型对象指向其构造函数的原型对象;(对象的原型对象是__proto__,构造函数的原型对象是prototype);
//因为比如,var arr = new Array(); arr.__proto__ === Array.prototype;//true
//这是对象的原型对象和构造函数的原型对象的之间的关系,
//直到arr.__proto__ 指向的是Array.prototype就足够了

//继承是为了复用代码,子类实例能访问父类属性,原型链的特性跟它相符:
//原型链上的对象跟继承有关,而继承通过原型对象体现:他们是怎样的一种关系;
//比如:注:JS用函数代替面向对象的类
function Animal(){
   this.isAnimal = true;
}
Animal.prototype.say = function(){
    console.log('say hello with ' + this.language);
}

function Cat(name, language){
    this.name = name;
    this.language = language;
}
//定义了两个‘类’,如何让Cat继承‘类’ Animal?
//利用原型,当实例化Cat时,

//cat.__proto__ === Cat.prototype; 
//那么cat.__proto__.__proto__ = Animal.prototype;
//Cat.prototype.__proto__ = Animal.prototype;
//但一般不这么做,原因可能是__proto__不是标准的规定;
//一般会这样实现继承: new  Animal();的结果是一个实例{__proto__: Animal.prototype}
Cat.prototype = new  Animal();
//保持prototype.constructor不变;实例的构造函数应该始终指向原本的构造函数
Cat.prototype.constructor = Cat;
//添加Cat自身的属性,这是所有Cat实例共用的属性。
Cat.prototype.printName = function(){console.log(this.name);}; 
var cat = new Cat('猫','喵');
cat;
//Cat{ 
//    language: "喵"
//    name: "猫"
//  __proto__: Animal
//      constructor: ƒ Cat(name, language)
//      isAnimal: true
//      printName: ƒ ()
//      __proto__:
//          say: ƒ ()
//          constructor: ƒ Animal()
//          __proto__: Object
//}
//只是这样的话,若父类实例有自身属性,这些属性也会随之添加到子类实例的原型上:
//像 isAnimal 这样的属性被添加到 cat.__proto__上面;看着有点奇怪;
//ES6有个方法Object.create(proto, descriptors);可以忽略父类实例的属性
//Object.create(proto, descriptors)是创建一个原型对象指向proto的对象
Cat.prototype = Object.create(Animal.prototype);

//JS的原始构造函数,以及之间的关系  ----------------
//Array, Number, Boolean, String, Object
//基本所有实例都继承于Object;
//比如Array构造函数,Array有自己的prototype,Array继承于Object;
//Array.prototype.__proto__ === Object.prototype;
console.log(Array.prototype.__proto__ === Object.prototype);
console.log(Animal.prototype.__proto__ === Object.prototype);
//有一点需要注意 函数如Animal(或者由new Function('')生成的函数),
//可以认为是Function的实例,Animal.__proto__ === Function.prototype;
//但是Animal.__proto__不在new Animal()的实例的原型链上;
//但是函数可以访问Function的prototype上的属性;
Function.prototype.func = true;
Animal.func;
//true
console.log(Animal.prototype.__proto__ === Object.prototype);
//true
console.log(Function.prototype.__proto__ === Object.prototype);
//true
//基本可以认为Object的原型处在圆形链的顶端;
console.log(Object.prototype.__proto__);
//null

参考文档:

继承与原型链

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值