原型与原型链
一:原型
1.定义:原型是Funtion对象中的一个属性,它定义了构造函数制造出的对象的共同祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。
//Person.prototype ----原型 一个对象 当一个函数被定义时它就存在,自身带的属性
//Person.prototype = {} 是祖先
Person.prototype.Firstname = "li"
Person.prototypr.Lastname = "Am"
//或者
//Person.prototype = {
// Firstname: "li",
// Lastname:"Am"
//}
function Person (Lastname) {
this.Lastname = Lastname;
}
var person = new Person(Bm);
var person1 = new Person(Cm);
console.log(person.Fiestname,person.Lastname);
//输出“li Bm”,虽然 new Person()之中没有name属性,但是它会从它的Person.prototype(原型)中继承,如果 new Person()中有该属性那么就会用自己的属性而不会用原型的属性。
console.log(person.Firstname,person.Lastname);//也是输出“li Cm”,以为它和person1用的是同一个原型;
2.应用:可以利用原型提取公共属性
-
比如上面中的Firstname就相当与公共属性,在原型中增加该属性可以减少耦合;
3.增删改查(通过子代)
-
增删改
-
基本上只能通过函数的原型来修改(Person.protoype.Firstname = "wang").
-
通过new的对象来修改基本上不可能
-
-
查
-
只有被继承时才会显示
-
4.prototye.constructor(构造器)
Person.prototype = {
//看似为空,其实其中有两个隐式属性,为系统自设;
/*constructor:Person(), 是构造出这个原型的函数---可以手动更改
_proto_:object 详下一个*/
}
function Noething (){
}
Person.prototype.constructor = Noething//此时Person.prototype.constructor 为noething。
5.prototype.proto
function Car () {
/*new 的全过程 --- 隐式过程
var this = {
__proto__:Car.prototype ---- 相当于起到联接原型的作用
};
.....(执行函数内容)
return this*/
}
var car = new Car();
二:原型链
-
通过—proto—来联接原型,使其形成链
Grand.prototype.Lastname = "li";
function Grand () {
}
var grand = new Grand();
Father.prototype = grand;
function Father() {
this.name = "Am";
this.money = "20W";
this.key = {
key1:"200"
};
}
var father = new Father();
Son.prototype = father;
function Son () {
this.name = "Bm";
this.age = 18;
}
var son = new Son();
//假如出现没有的属性会一层一层的往上寻找 son->Son.prototype.__proto__(father)->Father.prototype.__proto__(grand)->Grand.prototype.__proto__(Object)->Object.prototype.__proto__(null) ————终端
console.log(son.name)//输出“Bm”
console.log(son.money)//输出"20W"
console.log(son.Lastname)//输出“li”
//增删改查 ---其实与原型差不多
son.Lastname = "wu"//这里是son本身加了一个属性,而非将Grand的Lastname修改为"wu"----增删改一样也(换句话就是通过子代修改父代基本上不能实现)
//特例-----针对于引用值(方法的修改,而不是覆盖/赋值的修改)
son.key.key2 = "300"//这里就可以将Father.key添加一个key2 = "300"的属性,而son并没有该属性,因为对于调用应用值它操作的是它直接(简而言之就是son.key.key2这里只是在操做key这个对象,son.key是调用了key)
Man.prototype = {
name: "Am",
height: 100,
say: function (){
console.log(this.name);
}
}
function Man (){
this.name = "Bm";
this.eat = function(){
this.height ++;
}
}
var man = new Man()
man.say();//输出“Bm”,方法中的this指向---谁调用的就指向谁
man.eat();//man中会添加一个height属性并且值为101,首先调用eat()后会执行this.height ++,因为man自身没有height所以就会继承原型的height并且++后添加到man中
三:Objec.create()所创建的对象
// var obj = Object.create(原型) --------create()括号中只能填“对象”或者"null"
var obj = {
name: "li",
age: 19
}
var obj1 = Object.create(obj);//此时obj1的原型为obj
//因为create()可以填null,所以导致其创建出的对象可能没有原型
var obj2 = Object.create(null);
//此时obj2没有原型;
-
由上所得:只是绝大多数对象最终会继承自Object.prototype
四:call/play
-
作用:改变this指向
function Person (name, age) {
this.name = name;
this.age = age;
}
var person = new Person()
var obj = {
}
Person.call(obj,"wu",20);//改变this指向,相当于在Person函数中顶部新增(this = obj),而后面两个是传入的参数
//实际上: Person() === person.call()
//此时;obj = {
// name: "wu",
// age: 20
//}
function Person (age,name){
this.name = name;
this.age = age;
}
/*假如也有一个构造函数需要实现的功能包括了上面的构造函数,如:
function Student (age,name,socor) {
this.name = name;
this.age = age;
this.socor = socor;
}*/
//那么就可以用call的方法简化代码
function Student (age,name,socor) {
Person.call(this,age,name);
this.socor = socor;
}
var student = new Student;
-
apply其实与call差不多,只有一点区别
-
传参方式的不同
-
call:需要把实参按照形参的个数传进去
-
apply:传入的是一个arguments(实参列表)----数组
-
function Student (age,name,socor) { Person.apply(this,[age,name]); this.socor = socor; }
-