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