• 原型以及原型链的学习随笔



    一 原型: 

    1 定义:原型是function对像的一个属性,他定义了构造函数制造出的对象的公共祖先;

    通过该构造函数产生的对象,可以继承该原型的属性和方法。

    原型也是对像。prototype;

    Person.prototype.name = 'jams';

    function Person(){

     

    }

    var person = new Person();

    当打印:console.log(person.name)时,会先从函数中找看下有没有这个属性值,如果没有就去原型prototype中找;

    因此,这时候打印出来的值为:jams 

    prototype 是函数对象默认的属性,可以增删改查; 

    2 利用原型特点和概念,可以提取共有属性;

    3对象如何查看原型——>隐式属性:__proto__

      __proto__ 中存放的就是构造函数的原型

    相当于:在函数中隐藏了一段代码: var  this = {

    __proto__: Person.prototype

      举个例子:

    var obj = { name: 'a'}

    var obj1 = obj;

     obj = {name : 'b'}

    console.log(obj1.name);// 输出的值为 a 

    console.log(obj.name);// 输出的值为 b 
      对比:

      var obj = { name: 'a'}

    var obj1 = obj;

       obj.name ='b'

    console.log(obj1.name);// 输出的值为 b 

    console.log(obj.name);// 输出的值为 b 

     

      原因: 当你修改obj.name 时,修改的是原型中的值,当你重新附值给obj时(obj={name:'b'}),相当于重新定义了obj这个变量;

    换个理解方式为,obj.name 是一个指针,而obj 是一个变量; 

     

    4 对象如何查看对象的构造函数:constructor;

    constructor 是默认自带的一个属性,他的值指向原函数;

    二 原型链: 

    1如何构成原型链: 一级一级往上找;

     举个栗子: 

     Grand.prototype.lastName = 'a';

    function Grand(){

      var grand = new Grand();

    Father.prototype = grand;

    function Father() {

    this.name =  ' b '; 

    var father = new Father(); 

      Son.prototype = father;

    function Son(){

    this.hobbit = 'smoke';

    }

    var son = new Son(); 

      console.log( son.name );  // b

    console.log(son.lastName); // a

      2 原型链上属性的增删改查:跟原型上的增删改查基本一致,其中删除:delete 只能通过原型prototype 才能删除原型的值;

     

    Person.prototype = {

    name = 'a',

    sayName : function(){

      console.log(this.name);

    }

    function Person(){ 

      this.name = 'b';

      var person = new Person();

      sayName 里面的this指向是,谁调用的这个方法,this指向谁;

      所以最终结果person.sayName() 的值为b

    而Person.prototype.sayName() 的值为a 

      3绝大多数对象的最终都会继承自Object.prototype

    但不是所有的对象都可以继承,特例:Object.creat()原型;

    例如:object.creat(null) ,该对象没有prototype原型;

    4原型链的重写:

    例如常见的如下原型链就是经常被重写试用的,当然自己定义的原型同样也是可以被重写 

    Object.prototype.toString

    Number.prototype.toString

    Array.prototype.toString

    Boolean.prototype.toString

    String.prototype.toString 

    (题外话:JS 有个小bug:

    控制台运算:0.14*100,去看下运算结果: 14.000000000000002  这是js精度不准问题导致的;

     解决方法:小数先乘以100然后向下取整或向上取整。如果利用保留两位有效数字的方法toFixed()再乘以100是不准确的;

    math.random() 会产生一个(0,1)的随机数 

    toFixed() 保留两位有效数字 

    Math.tofloor() 向下取整

    Math.toceil() 向上取整; 

    var num =Math.tofloor(Math.random()*1000);  // 获取0-100的随机数;

     ) 

    三 call、apply

     call、apply的作用:可以借助别人的函数实现自己的功能 

    call 可以该表this指向

    例如:

    function Person(name,age){

     //this == obj;

    this.name = name;

    this.age = age; 

    var person = new Person( 'a' ,100);

    var obj = {}

    Person.call(obj, 'b' ,300);

     这句话的意思就是调用Person的方法,然后将相关值附值给obj,使得obj有相关参数属性值;

     执行结果:obj

    {name: "b", age: 300}

    这样的好处,借用Person的方法来封装了obj; 

    例如:

    function Person(name,age,sex){

    this.name  =  name;

    this.age = age;

    this.sex = sex; 

    function otherInformation(tel,grade){

    this.tel = tel;

    this.grade = grade; 

    function Student(name,age,sex,tel,grade) {

    Person.call(this,name,age,sex);


    otherInformation.call(this,tel,grade)

    }

    var student = new Student('asd',123,'male',129,2018) ;

     输出结果:

    Student {name: "asd", age: 123, sex: "male", tel: 129, grade: 2018}

    call与apply的区别:后面传的参数形式(或者传参列表)不同; 

    apply 只能传两个参数,一个是this,另一个是数组,例如: Person.apply(this,[name,age,sex]);

    转载请注明出处


  • 相关阅读:
    第一部分 android display(sufaceflinger & overlay)
    UML类图关系大全
    第二部分 MediaPlayer的接口与架构
    Climbing Stairs
    Add Binary
    Plus One
    Unique Paths
    Length of Last Word
    Count and Say
    Valid Sudoku
  • 原文地址:https://www.cnblogs.com/Anderson-An/p/9942805.html
Copyright © 2020-2023  润新知