180331 原型

  • 原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。
  • 通过该构造函数产生的对象,可以继承该原型的属性和方法。
  • 原型也是对象。
  • 原型就像是批处理添加水印:预设好的统一处理,有颜色主题不合适的单独设计。

  • 访问对象的属性,如果本身没有,会向原型上面找。

  • 由构造函数创建的对象,有隠式属性this对象。

  • this对象有一个属性 _ proto_ [指针,指向对象的原型]

  • this . _ proto_ = Function.prototype

  • 由构造函数创建的对象的属性[this]的属性[_ proto_]的值等于构造函数的属性[prototype]的值。

  • 这两个指向的值是一个对象,即原型对象。

obj.attributes 
-> 
if(obj.attributes){return obj._proto_.attributes}

原型应用:

CarFactory.prototype.door = 4;
CarFactory.prototype.distance = 0;
CarFactory.prototype.run = function() {
    this.distance += 100;
}
CarFactory.prototype.aurhor = {
        name: 'cst',
        money: 999999
    }
    //提取全部实例的公共特点,添加到远行对象里
    //相当于给每一个实例初始化,添加水印,节约性能

function CarFactory(wheelNum, carColor) {
    this.wheel = wheelNum;
    this.color = carColor;
}
var oCar1 = new CarFactory(3, 'red');
var oCar2 = new CarFactory(5,'yellow');
        oCar1.door = 6;
// 实例本身新增door属性,就不会找原型,也不会影响原型和其他实例
console.log(oCar.door);

delete oCar1.chair; // true 删除不存在的属性

oCar1.author.money = 200;
console.log(oCar2.author.money);   // 改变实例本身属性,还是改变原型属性

[改变原型对象的指向] 和 [改变原型对象内的值]

CarFactory.prototype.door = 4;
var oCar1 = new CarFactory();
CarFactory.prototype = {
    door:6;   //已经创建好的对象不会被新改变的原型影响
}

// this._proto_ --链接-- Function.prototype
// 这两个值对应的是一个对象,过程是F.p把地址给了t._p_
// 当改变了F.p,它会指向一个新的对象,有一个新的地址
// 而t._p_还是以前的地址
// 两个值不是时刻牵引的,是一次性赋给相同地址,之后撒手
// 让F.p等于一个新对象,相当于断开了与t._p_的联系与羁绊
// 让F.p.attributes等于一个新的值,并没有断开两者的联系,
// 因此会出现给F.p赋值新对象不会影响已经创建的对象
// 而给F.p赋值新的属性值,会影响已经创建的对象
// 因为联系还在,f._p_是跟着对象走的
// 两个都是属性名而已,两张入场券,进入同一个地方,这个地方里面存着原型信息
// 要在一张入场券上增加或修改演员,要么把入场券引向别的场次
// 跟对象直接联系的是__proto__,只要看它的值就行了,是保持链接属性更新。
// 还是断开链接,属性不变

var PrototypeSelf = {name:'cst'};
var __proto__Self = PrototypeSelf;
PrototypeSelf = {name:'duyi'};
__Proto__Self.name  // -> cst

练习

Person.prototype.name = 'sunny';

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


//======================================


Person.prototype.name = 'sunny';

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


//======================================


Person.prototype.name = 'sunny';

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

//=======================================

Person.prototype.name = 'sunny';

function Person() {}
Person.prototype = {
    name: 'cherry'
};
var oPerson = new Person();
console.log(oPerson.name); // cherry

查询对象构造函数

object.prototype

原型链

GrandFather.prototype.lastName = 'yang';

function GrandFather() {
    this.bike = 1;
}
Father.prototype = new GrandFather();

function Father() {
    this.fortune = {
        money: 999999,
        house: 4
    }
    this.name = 'jaja'
}
Son.prototype = new Father();

function Son() {
    this.name = 'heihei',
        this.age = 20
}

var oSon = new Son();
console.log(oSon.lastName);

oSon.fortune.house += 1;  //访问fortune对象的属性并赋值,改变相同地址的引用值, 相当于改变原型上的属性
oSon.fortune = {};       //将fortune属性指向另一个对象地址,换了一个引用值, 相当于给oSon自己添加属性

var oSon2 = new Son();
console.log(oSon2.fortune.house);   //  5  这个是引用值,后续会受影响  

这里写图片描述

  • 除(object.create()创建的对象之外),沿着原型链一直向上游查询,找到头都是object.prototype -> {}
  • 函数的原型对象constructor默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针proto,该指针指向上一层的原型对象,而上一层的原型对象的结构依然类似,这样利用proto一直指向Object的原型对象上,而Object的原型对象用Object.prototype.proto = null表示原型链的最顶端,如此变形成了javascript的原型链继承,同时也解释了为什么所有的javascript对象都具有Object的基本方法。
    这里写图片描述

原型方法的重写

如果原型链中上游已经有一个函数,可以在下游重新定义。

改变this指向

function.call(host,num1,num2)
function.apply(host,[num1,num2])

function test(){
    console.log(this);
}
test();   //thiswindow

相当于window.test.call(window);

function.call(调用者)
function Person(name, age) {
    this.name = name;
    this.age = age;
}

function Student(name, age, myClass, myGrade) {
    Person(); // !!没有写出来是谁调用的,都是window调用
    Person.call(this, name, age); // Studnet函数调用Person函数,保证Person函数的参数
} // call(name,age)->Student(name,age)->Student(实参)
// this是当前调用的函数Student
new Student('cst', 18, 2, 4); //构造函数会在内部隠式创建this对象并返回,
//原因是构造函数本身就是用于创建对象并初始化
//构造函数身份象征:new

var numObj = {
    x: 1,
    y: 2
}

function add(a, b) {
    console.log(this.x + a + this.y + b);
}
add(); // NaN
add.call(numObj, 3, 4); // 10

继承

圣杯模式:闭包

var inherit = (function() {
    var Cache = function() {}; //缓存函数,每次执行都需要创建一个,没有必要,写入闭包
    return function(Target, Origin) {
        Cache.prototype = Origin.prototype; //下游不影响上游
        Target.prototype = new Cache();
        Target.prototype.constructor = Target;
        Target.prototype.uber = Origin;
    }
})();

这里写图片描述


防止变量污染

立即执行函数

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章