美文网首页
原型 原型链 call apply 继承 闭包补充—JS学习笔记

原型 原型链 call apply 继承 闭包补充—JS学习笔记

作者: 大大大l脸 | 来源:发表于2019-01-23 20:19 被阅读32次

    原型

    1.定义:

    原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。
    例如:

     function Someone() {  };
     var someone1 = new Someone();
     var someone2 = new Someone();
    

    Someone.prototype --原型对象
    Someone.prototype={ } 是祖先:由Someone这个构造函数制造出的对象(someone1,someone2等 )的祖先。每new一次,都产生新的对象,这些对象都继承该原型的属性和方法。

    2.利用原型特点和概念,可以提取共有属性。
     // 提取共有祖先:
            Car.prototype.height = 1400;
            Car.prototype.lang = 4900;
            Car.prototype.carName = "BMW";
    
            function Car(color, uesr) {
                // this.height = 1400;
                // this.lang = 4900;
                // this.carName = 'BMW';
                this.color = color;
                this. uesr =  uesr;
    
            }
            var car = new Car('red', 'David');
            var car1 = new Car('orange', 'Kangkang');
    
    
    3对象和原型的增删

    对象的增删(接上段代码)

    car.weight = '50 kg'; 
    delete car.color; //对象的属性删除了
    console.log(car.color) //undefined
    console.log(car1.color) //orange
    

    原型的增删(接上段代码)

    console.log(car1.lang) // 4900
    delete car1.lang; // car1.lang=4900.car1的lang的属性值是原型上的值,因此如果要删除lang的值 也是要在原型上删除。
    console.log(car1.lang) // 4900
    delete Car.prototype.lang;
    console.log(car.lang); // undefined
    console.log(car1.lang); // undefined、
    
    4对象查看原型 — > 隐式属性 proto
    5.对象如何查看对象的构造函数 — > constructor

    constructor 是查看对象的构造函数

      Teacher.prototype.key = "abc";
    
     function Teacher(name) {
      //  var this={ __proto__:Teacher.prototype};
      this.name = name;
      this.subject = 'English';
    
      };
    var student1 = new Teacher('David');
    var student2 = new Teacher('Kangkang');
    console.log(Teacher);
     // function Teacher(name) {this.name = name;this.subject = 'English'; }
    console.log(student1); 
    // {name: "David", subject: "English" , _proto__: Objectc ————>onstructor: function Teacher(name) { this.name = name; this.subject = 'English'; },  __proto__: Object}
    console.log(student1.__proto__);
     // {key: "abc",constructor: function Teacher(name) { this.name = name; this.subject = 'English'; },  __proto__: Object}
    console.log(student1.key); // "abc"
    
     var OMB = {
            key: '123',
            }
    
     student1.__proto__ = OMB; // {key: "123",  __proto__: Object}
    
      console.log(student1.__proto__);
      console.log(student1.key); //"123"
    

    案例1:更改了属性值

    
    Person.prototype.name = 'sunny';
    
     function Person() {   }
    
     var person = new Person();
     console.log(person.name); //"sunny"
    
     Person.prototype.name = 'cherry';
     console.log(person.name); //"cherry"
    

    案例2 :更改对象。

    
     Person1.prototype.name = 'sunny1';
    
     function Person1() {
            //  var this={__proto__:Person1.prototype}; 每次new 一个对象时 才会有这样的隐式语句。
     
       }
       var person1 = new Person1(); // 在function Person1{   隐式的执行 var this={__proto__:Person1.prototype};}
    
       console.log(person1.name); //"sunny1"
       console.log(person1);
       Person1.prototype = {
            name: 'cherry1'
            };
    console.log(person1.name); // "sunny1"
     console.log(person1);
    
    

    解析案例二:
    Person1.prototype.name="sunny1";
    由构造函数Person1而来的新建对象的 --proto--:Person1.prototype;
    Person1.prototype={ name:"cherry1"}
    Person1.prototype 是原型对象的名字,是个指针,却不能完全指代对象全部内容。
    刚开始由构造函数Person1制造的对象person1有个属性是_ --proto--,它的值是:指针名字叫Person1.prototype的原型对象。后来这个指针不在指向原型对象,指向新建的{name:"cherry1"}对象。
    但是由构造函数Person1制造的对象person1的属性是 --proto--却还是指向原型对象,不会因此改变指向。

    容易犯错:

     Person1.prototype.name = 'sunny1';
     function Person1() {};
     Person1.prototype = {name: 'cherry1'};
     var person1 = new Person1(); 
     //在function Person1{   隐式的执行 var this={__proto__:Person1.prototype};}
     console.log(person1.name);    //cherry1
    

    难点: Person.prototype constructor --proto-- 三者之间的联系

    原型链

    1,如何构成原型链?,
    2,原型链上属性的增删改查
    3,谁调用的方法内部this就是谁-原型案例
    4,对象的最终都会继承自Object.prototype(不是所有 因为null 不会继承Object.prototype

    5,object.create(原型);
    6,原型方法上的重写

    构成原型链的案例(1 传统继承)

    function Grand() {};
     var grand = new Grand();
     Father.prototype = grand;
     function Father() {
           this.name = 'xuming';
            this.fortune = {
                    card1: 'visa',
                };
            this.num = 100;
    
     };
    
     var father = new Father();
     Son.prototype = father;
    
     function Son() {
            this.hobbit = 'smoke';
      }
      var son = new Son();
     console.log(son.hobbit); //smoke
     console.log(son.name); //xuming
      son.fortune.card2 = 'master';
    // son 依然没有fortune属性。调用son.fortune对象的引用值为他添加card2的属性并附值。
      son.num++;
     console.log(son.num); 
    // 101  son.num=son.num+1;取过来自身+1;但是无法修改father的值
     console.log(father.num); //100
    

    案例:qian 每次调用 eat 方法的 weight对应的值 都会+1

            Qian.prototype = {
                weight: 150,
            }
    
            function Qian() {
                this.eat = function() {
                    this.weight++;
                }
            }
            var qian = new Qian();
            console.log(qian); //{eat:fn}
            console.log(qian.weight); //150 原型上面有weight 这个属性值
            qian.eat();
            console.log(qian.weight) //151  新对象qian每次调用一个eat方法,
    

    Object.create(原型) Object.create(null) //()内必须写对象或者null 否则会报错
    undefined null 这两个都是原始值没有原型对象 (Objec.creat(null)也没有原型对象,除了这三个 其他都有)因此不能调用toString 方法
    下面案例解析:
    anotherObject 的原型是 myObject,但是由此方法创建的对象却没有。prototype和constructor。因此此类对象无法用 instanceof(A instanceof B →A的constrcutor值是不是B,)

    anotherObject = {
    a:2
    };
    var myObject = Object.create( anotherObject, {
    b: {
    enumerable: false,
    writable: true,
    configurable: false,
    value: 3
    },
    c: {
    enumerable: true,
    writable: false,
    configurable: false,
    value: 4
    }
    });
    myObject.hasOwnProperty( "a" );  // false hasOwnProperty判断是否是自己的直接属性
    myObject.hasOwnProperty( "b" ); // true
    myObject.hasOwnProperty( "c" ); // true
    myObject.a; // 2
    myObject.b; // 3
    myObject.c; //4
    
       var obj = Object.create(null)
            console.log(obj); // {} No prototypies
            obj.name = "王二麻子";
            console.log(obj); // {name :"王二麻子"}
            obj.__proto__ = {
                age: 123
            };
            console.log(obj); 
    //{ name :"王二麻子",__proto__:Object,——>{age:123,__proto__:Object}}
            console.log(obj.age); //undefined
    
    .call(object,,,) apply(object,[ ]) 改变函数的this指向

    区别是传参列表不一样,call只能传实参,需要把实参按照形参的个数传进去,apply只能传一个数组形式的参数
    利用别的函数实现自己的功能,能够减少代码量 。

    应用案例:(2借用构造函数 继承)

     function Model(name, color, age) {
                this.name = name;
                this.color = color;
                this.age = age;
    
            }
    
            function Example(name, color, age, user, brand) {
    
                Model.call(this, name, color, age);
     //利用Model实现Examplef的功能,让Model内的this 指向了call()内的对象this(这个this其实指的是Example构造函数构造的新对象))Model的参数还能正常传参数。
    //
    
                this.user = user;
                this.brand = brand;
    
            }
            var living = new Example('王者', 'red', 18, 'I', '名牌')
    

    关于继承,
    1.传统形式:过多的继承了没用的属性
    比如:

    Grand.prototype.name = "ji";
    function Grand(){}
    var grand = Grand();
    Son.prototype = grand;
    function Son(){}
    var son = new Son();
    

    2.借用构造函数:不能继承借用构造函数的原型,每次构造函数都要多走一个函数。

    3.共享原型不能随便改动自己的原型。

    Father.prototype.lastName = "Q";
    function Father(){}
    function Son(){}
    Son.prototype = Father.prototype;
    var son = new Son();
    var father = new Father();
    function extend(Baby, Parent){
    Baby.prototype = Parent.prototype;
    }
    

    4.圣杯模式

     function inherit(Target, Origin) {
           function F() {};
          F.prototype = Origin.prototype;
            Target.prototype = new F();
           Target.prototype.constuctor = Target; 
           Target.prototype.uber = Origin.prototype; 
    
      }
    Father.prototype.Lastname = "赵钱孙李"
    
     function Son() {}
     function Father() {}
     inherit(Son, Father)
     var son = new Son();
      var father = new Father();
      //  son.__proto__  ——>new F()————>new F().__proto__  ————> Father.prototype 此时son.constructor:function Father(){};
     // 此时new F() 虽然为son的原型对象 但是非定义在全局的作用域内 因此无法显示。
     
    

    YUI 雅虎

    圣杯模式的源码,优化继承,子不干父

    
     var Inherit = (function() {
            var F = function() {}; //私有化变量 无法识别访问 
            return function(Target, Origin) {
                    F.prototype = Origin.prototype;
                    Target.prototype = new F();
                    Target.prototype.constuctor = Target;
                    Target.prototype.uber = Origin.prototype;
    
              }
    
            }());
    

    运用闭包防止全局变量污染,模块化开发

    function Deng(name, wife) {
                var prepareWife = " 赵小姐"; //私有化变量 无法访问
    
                this.name = name;
                this.wife = wife;
                this.divorce = function() {
                    this.wife = prepareWife;
                }
                this.sayPreparewife = function() {
                    console.log(prepareWife);
                }
    
         }
    
            var deng = new Deng('邓先生', '等太太');
    

    相关文章

      网友评论

          本文标题:原型 原型链 call apply 继承 闭包补充—JS学习笔记

          本文链接:https://www.haomeiwen.com/subject/rmwjjqtx.html