1映企、原型诡宗、原型鏈
? ? ? ? 1.1? ? 原型的定義:原型是function對(duì)象的一個(gè)屬性锹雏,原型定義了構(gòu)造函數(shù)制造出的對(duì)象的公共祖先要拂。通過該構(gòu)造函數(shù)產(chǎn)生的對(duì)象搁痛, 可以繼承該原型的屬性和方法。原型也是對(duì)象宇弛。
? ? ? ? ? ? ? ? 原型是該構(gòu)造函數(shù)構(gòu)造出對(duì)象的公有祖先
Person.prototype --> 原型是函數(shù)的一個(gè)屬性
//Person.prototype = {} 它就是公共祖先,是一個(gè)對(duì)象源请,在函數(shù)剛剛被創(chuàng)建時(shí)枪芒,就已經(jīng)被定義好了
Person.prototype.LastName = "Liu";
Person.prototype.say = function () {
console.log('hehe');
}
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
var person = new Person("zhangsan", 20, "male");
//person能夠繼承Person原型上的屬性和方法,person繼承了Person原型的LastName 屬性和say 方法
當(dāng)構(gòu)造函數(shù)自身與原型上有同一個(gè)屬性或方法谁尸,構(gòu)造出新對(duì)象時(shí)舅踪,取構(gòu)造函數(shù)自身的屬性或方法
利用原型的特點(diǎn)和概念,可以提取公有屬性
Car.prototype = {
height: 1400,
lang: 4900,
carName: "BMW"
}
function Car(color, owner) {
this.owner = owner;
this.color = color;
//下面三個(gè)屬性在每次構(gòu)造出對(duì)象時(shí)都要執(zhí)行良蛮,造成代碼的冗余抽碌,通過繼承解決(放到原型中)
// this.height = 1400;
// this.lang = 4900;
// this.carName = "BMW";
}
var car = new Car("red", "Liu");
var car1 = new Car("yellow", "Wang");
? ? ? ? 1.2? ? 原型的增刪改查
Person.prototype.LastName = "Zhang";
function Person(name) {
this.name = name;
}
var person = new Person("San");
(1)查:執(zhí)行person.LastName
(2)改:Person.prototype.LastName = "Wang";
(3)增:Person.prototype.Sex = "male";
(4)刪:delete關(guān)鍵字
? ? ? ? 1.3? ? constructor(構(gòu)造器)
? ? ? ? ? ? ? ? constructor屬性會(huì)返回構(gòu)造該對(duì)象的構(gòu)造函數(shù)
function Fn(){}
var test = new Fn();
//執(zhí)行test.constructor會(huì)返回function Fn(){}
? ? ? ? 1.4? ? __proto__
? ? ? ? ????????1.4.1????每個(gè)對(duì)象都具有一個(gè)名為__proto__的屬性
? ? ? ? ? ? ? ? 1.4.2????每個(gè)構(gòu)造函數(shù)(系統(tǒng)自帶的和自定義的)都有一個(gè)prototype方法,也就是說决瞳,prototype同樣有__proto__屬性
Person.prototype.name = "abc";
function Person(){
????????//var this = {
? ? ? ? ?//? ? ? ?__proto__ : Person.prototype? ? __proto__將person與Person.prototype連接起來
? ? ? ? //};
}
var person = new Person();
如果我們要訪問person.name货徙,它會(huì)先在自身的屬性中找有沒有name屬性,如果沒有皮胡,它就會(huì)沿著__proto__的指向痴颊,到Person.prototype里面去找
舉例
Person.prototype.name = "sunny";
function Person() {}
var person = new Person();
Person.prototype.name = "cherry";//更改了Person.prototype的屬性
訪問person.name,結(jié)果為cherry
舉例
Person.prototype.name = "sunny";
function Person() {
//在new Person時(shí)? ? var this = { __proto__ : Person.prototype}
}
var person = new Person();
Person.prototype = {
name : "cherry"
}
訪問person.name屡贺,結(jié)果為sunny
分析:引用值的互相賦值
Person.prototype = {name : "sunny"}
__proto__ =?Person.prototype;
Person.prototype? = {name : "cherry"}
2蠢棱、原型鏈
構(gòu)成原型鏈
//Grand.prototype.__proto__ = Object.prototype
Grand.prototype.LastName = 'Zhang';
function Grand() { }
var grand = new Grand();
Father.prototype = grand;
function Father() { this.name = 'San'; }
var father = new Father();
Son.prototype = father;
function Son() { this.habbit = 'somke'; }
var son = new Son();
son可以訪問son.LastName屬性
Person.prototype = {
????name: 'a',
????sayName: function () { console.log(this.name);}
}
function Person() { this.name = 'b'; }
var person = new Person();
//sayName里面的this的指向,誰調(diào)用的這個(gè)方法甩栈,this指向誰
? ? ? ? 2.1? ? Object.create(原型)
var obj = {
name: "sunny",
age: 20
};
var obj1 = Object.create(obj);
? ? ? ? 2.2????絕大多數(shù)對(duì)象的最終都會(huì)繼承自O(shè)bject.prototype
? ? ? ? ? ? ? ? 特殊情況:Object.create(null)泻仙,創(chuàng)建的對(duì)象沒有原型
3、call/apply
? ? ? ? 作用:改變this的指向
? ? ? ? 區(qū)別:call和apply的傳參列表不同
? ? ? ? 3.1? ? call
function Person(name, age) {
//this == obj
this.name = name;//this.name = name ==>obj.name = name
this.age = age;//this.age = age ==>obj.age = age
}
var person = new Person('Zhang', 20);
var obj = {};
Person.call(obj, "wang", 22);
call的第一個(gè)參數(shù)會(huì)改變this的指向量没,第二位以后的參數(shù)當(dāng)作實(shí)參傳遞到形參去玉转。
這里把obj傳到this去了,執(zhí)行時(shí)this變成了obj允蜈。
this舉例:
借用別人的函數(shù)冤吨,實(shí)現(xiàn)自己的功能
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
function Student(name, age, sex, tel, grade) {
//var this = {} 這里的this和call的第一個(gè)this是同一個(gè)this
Person.call(this, name, age, sex);
this.tel = tel;
this.grade = grade;
}
var student = new Student('sunny', 123, 'male', 139, 2015);
this舉例:
function Wheel(wheelSize, style) {
this.wheelSize = wheelSize;
this.style = style;
}
function Sit(c, sitColor) {
this.c = c; this.sitColor = sitColor;
}
function Model(height, width, len) {
this.height = height;
this.width = width;
this.len = len;
}
function Car(wheelSize, style, c, sitColor, height, width, len) {
//利用其他的函數(shù)實(shí)現(xiàn)功能
Wheel.call(this, wheelSize, style);
Sit.call(this, c, sitColor);
Model.call(this, height, width, len)
}
var car = new Car(100, "花哨", "真皮", "red", 1800, 1900, 4900);
? ? ? ? 3.2? ? apply
? ? ? ? 傳參時(shí)需要傳一個(gè)arguments(數(shù)組的形式)——實(shí)參列表蒿柳,其他方面和call沒有任何區(qū)別
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
function Student(name, age, sex, tel, grade) {
//var this = {} 這里的this和call的第一個(gè)this是同一個(gè)this
Person.call(this, [name, age, sex]);
this.tel = tel;
this.grade = grade;
}
var student = new Student('sunny', 123, 'male', 139, 2015);
4、繼承
? ? ? ? 4.1? ??傳統(tǒng)形式——>原型鏈:過多的繼承了沒用的屬性
Grand.prototype.lastName = "Liu"
function Grand() { }
var grand = new Grand();
Father.prototype = grand;
function Father() {
this.name = 'hehe';
}
var father = new Father();
Son.prototype = father;
function Son() { }
var son = new Son();
? ? ? ? 4.2????借用構(gòu)造函數(shù):不能繼承借用構(gòu)造函數(shù)的原型漩蟆、每次構(gòu)造函數(shù)都要多走一個(gè)函數(shù)
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
function Student(name, age, sex, grade) {
Person.call(this, name, age, sex);
this.grade = grade;
}
var student = new Student();
? ? ? ? 4.3? ? 共享原型:不能隨便改動(dòng)自己的原型
Father.prototype.lastName = 'Liu';
function Father() {}
function Son() {}
function extend(Target, Origin) {
Target.prototype = Origin.prototype;
}
extend(Son, Father);
var son = new Son();
//不能給Son加一個(gè)獨(dú)立的屬性
? ? ? ? 4.4????圣杯模式 最完美的繼承模式
//C繼承A
// function B() { }
// B.prototype = A.prototype
// C.prototype = new B();
function extend(Target, Origin) {
function F() {};
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;//把a(bǔ)的constuctor指向自己
Target.prototype.uber = Origin.prototype;//Target真正繼承自O(shè)rigin
}
function A() {}
function B() {}
extend(A, B);
var A = new A();
var b = new B();
//現(xiàn)在給a增加獨(dú)立的屬性不會(huì)影響b
//a.__proto__--> new F().__proto__-->b.prototype a的構(gòu)造器指向的是b