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

原型

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('邓先生', '等太太');

猜你喜欢

转载自blog.csdn.net/weixin_33871366/article/details/87530512
今日推荐