js 原型与原型链

js 原型与原型链

原型

原型的概念的理解

  • 原型是function构造函数的一个属性,它定义了构造函数制造出的对象的公共祖先,通过此构造函数产生的对象,继承了该原型的属性和方法,原型也是对象
  • 所有的引用类型都有一个’_ _ proto_ _'属性(也叫隐式原型,它是一个普通的对象)。
  • 所有的函数都有一个’prototype’属性(这也叫显式原型,它也是一个普通的对象)。
  • 所有引用类型,它的’_ _ proto_ _'属性指向它的构造函数的’prototype’属性。
  • 当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它的’_ _ proto_ _'属性(也就是它的构造函数的’prototype’属性)中去寻找。

构造函数及prototype

  function Person() {
        this.name = "aaa";
  };
  Person.prototype //此时,会输出
  {
  constructor:f Person()
  _proto_:Object
  }
说明:
//Person.prototype 就是Person函数的原型,它也是一个对象,此对象中的constructor指针,指向Person构造函数本身,
//其目的就是不管自己的子孙(即Person构造函数构造的所有对象)走到哪儿,都知道自己是谁生的,友友们理解。。。;
//_proto_指针指向了Object函数的原型(后面再详细分析);

修改构造函数原型,其对象是否继承

  • 原型上添加属性或方法
   Person.prototype.name = "a";
   function  Person() {}
    --此时,Person.prototype对象中会多出一个属性name,值为a;
   var  per1 = new Person(); //用构造函数创建对象
   
   // 此时per1对象没有prototype属性,但per1对象有_proto_属性,这是怎么回事了啦,其实是这样的,
   // 我们在用new 关键字创建对象时,其时js会偷偷的在构造函数创建出的对象里发生下面的事
      this._proto_ = {_proto_:Person.prototype,}
   所以会有,per1._proto_指针指向Person函数原型的结果
   因此,per1.name // 会输出 a   per1通过_proto_属性找到了Person函数原型下的name属性;
  • 覆盖默认原型
   Person.prototype.name = "a";
   function  Person() {}
   // 此时 Person函数的原型会是
   {
    name:"a"
    constructor:ƒ Person()
	__proto__:Object
  }
   //若作如下修改
   Person.prototype= {
       name:"ccc"
   };
   //此时,Person函数的原型会是
   {
   name: "ccc"
   __proto__: Object
   }
   //覆盖constructor和原来添加的原型属性

原型链

原型的构成及原型链上属性的修改

A.prototype.lastname = "我是a";
 function  A() {
     this.a = "A";
 }
 var a = new A();
// 把a对象复制给B函数的原型
 B.prototype = a;
 function B() {
    this.b = "B";
    this.num = 100;
    this.fortune = {
        "car":"BM"
    }
 }
 var b = new B();
// 把b对象赋值给C函数的原型
 C.prototype = b;
 function C() {
     this.c = "C";
 }
 var  c = new C();

1、构成原型链
以上代码构成如下的原型链条
在这里插入图片描述
说明:
首先,c的构造函数是C()。所以:
c. _ proto _=== C.prototype === b,以此类推,b同c,
a的构造函数是A()。所以:
a. _ proto _=== A.prototype ,
又因为A.prototype是一个普通的对象,它的构造函数是Object,所以:
a.prototype. _ proto _=== Object.prototype
**2、原型链上属性的操作
**
2.1
执行:
c.num++;
操作
c.num // 输出101
b.num; //101
分析:c.num++相当于
c.num = c.num+1;等式右边的c.num通过原型链c._proto_找到C的原型b下面的num=100;拿到值加1为101,
然后在赋值给 c.num,相当于给c对象添 加值为101的属性num,截图如下:
在这里插入图片描述
2.2
执行:c.fortune = {car:‘byd’};
c.fortune.car; // 输出 byd
b.fortune.car //输出 BM
原理同上,不再赘述。
3、原型链上的操作2

   Dog.prototype = {
       height:100,
   }
   function Dog() {
       this.hanlder = function () {
           this.height++;
       }
   }
   var dog1 =new Dog();
   //说明:
    //dog1.height // 增加了height属性,并赋值为101
    //原型不变

创建对象的方式,

字面量方式

var a= {};

构造器方式

function A(){}
var a = new A();

object.create方式

var bbb = {}
var a = Object.create(null); // a 对象无原型链
var a = Object.create(bbb);

call/apply

作用及区别

作用:改变this指向,通俗点就是借用别人的函数实现自己的逻辑
区别:传参形式不同

调用

 function  P(name,age) {
       this.name = name;
       this.age = age
   }
   var p = new P("XX",20);
   var obj = {};

  //正常方法test()相当于test.call();
  //正常调用函数时,不new 内部this指向window new 后函数内部生成this = {}
   P.call(obj,"bbb",55);//  this指向obj  call需要把实参按照形参的个数传递
   p.apply(obj,["bbb",55]); // this指向obj   apply需要传递一个arguments
   //此时
   obj = {
     name: "bbb",
     age: 55
     __proto__:Object
	}
  

利用call/apply实现代码的优化

优化前:

  function teacher(name,age) {
        this.name = name;
        this.age = age;
    }
   function student(name,age,sex) {
       this.name = name;
       this.age = age;
       this.sex =sex;
   }
   var teacher= new teacher("aa",23)
   var student = new student("aa",23,"man")

优化后

  function teacher(name,age) {
        this.name = name;
        this.age = age;
    }
   //利用优化后
   function student(name,age,sex) {
       teacher.call(this,name,age); //call需要把实参按照形参的个数传递
       //teacher.apply(this,[name,age]) // apply需要传递一个arguments
       this.sex =sex;
   }
   var student = new student("aa",23,"man")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值