原型
- 定义:原型是function对象的一个属性,他定义了构造函数制造出的对象的公共祖先.通过该构造函数的对象,可以继承该原型的属性和方法.原型也是对象.
- 利用原型特点和概念,可以提取共有属性
- 对象如何查看原型–> 隐式属性 proto
- 对象如何查看对象的构造函数–> constructor
// 1. 原型对象的公共祖先
function Cat() {}
function Dog() {}
Dog.prototype
Cat.prototype
// 2.原型是一个对象,
Cat.prototype = {
lastName : 'cat',
cry : function () {
document.write('喵喵喵...');
}
};
Dog.prototype.lastName = 'dog';
Dog.prototype.cry = function () {
document.write('汪汪汪...')
}
function Cat() {
}
function Dog() {
}
// 3.通过该构造函数的对象,可以继承该原型的属性和方法
Cat.prototype = {
lastName : 'cat',
cry : function () {
document.write('喵喵喵...');
}
};
Dog.prototype.lastName = 'dog';
Dog.prototype.cry = function () {
document.write('汪汪汪...')
}
function Cat() {
}
function Dog() {
}
var cat = new Cat();
var cat1 = new Cat();
var dog = new Dog();
console.log(cat.lastName); // cat
console.log(cat1.lastName); // cat
console.log(dog.lastName); // dog
cat.cry();
cat1.cry();
dog.cry();
// 4.通过该构造函数的对象(以下简称对象),不可以修改/删除/赋值 继承该原型(以下简称原型)的属性和方法;对象的属性和方法与原型有相同属性和方法时,读取的为对象属性和方法;
Cat.prototype = {
lastName : 'cat',
cry : function () {
document.write('喵喵喵...');
}
};
Dog.prototype.lastName = 'dog';
Dog.prototype.cry = function () {
document.write('汪汪汪...')
}
function Cat() {
}
function Dog() {
}
var cat = new Cat();
var cat1 = new Cat();
var dog = new Dog();
cat.lastName = 'catt';
//
console.log(Cat.prototype.lastName);// cat
console.log(cat.lastName); // catt
Cat.prototype.lastName = 'cattt';
console.log(Cat.prototype.lastName);// cattt
console.log(cat.lastName); // catt
// 5. 对象的构造函数constructor
function Cat() {}
function Dog() {
}
var cat = new Cat();
var dog = new Dog();
console.log(cat.constructor);//ƒ Cat() {}
// constructor 并不是我们定义的,那么他是哪儿来的呢?由以上知识点猜测:继承
// 如果有一天找不到cat的构造方法了,可以通过cat.constructor去找寻
console.log(Cat.prototype); // 果真有constructor 见图一
图一
// 6. 对象的构造函数可以改变
function Dog() {}
function Cat() {}
var cat = new Cat();
var dog = new Dog();
console.log(cat.constructor);//ƒ Cat() {}
console.log(Cat.prototype);
Cat.prototype = {
constructor : Dog
};
var cat1 = new Cat();
console.log(cat.constructor);//ƒ Cat() {}
console.log(cat1.constructor);//ƒ Dog() {}
// 7, proto
// 隐式的this,中有一个属性,指向的是改对象的原型
function Dog() {
// var this = {
// __proto__ : Dog.prototype
// }
}
// 8. proto 指向是可以更改的
Cat.prototype.name = 'cat';
function Cat() {
// var this = {
// __proto__ : Cat.prototype
// }
}
var Obj = {
name : 'obj'
};
var cat = new Cat();
cat.__proto__ = Obj;
console.log(cat.name);// obj
// 9. prototype修改方式遇到的问题
// 1.属性值更改
Person.prototype.name = 'sunny';
function Person() {
}
Person.prototype.name = 'cherry';
var p = new Person();
console.log(p.name);// cherry
// 2.原型更改
Person.prototype.name = 'sunny';
function Person() {
}
var p = new Person();
Person.prototype = {
name : 'cherry'
};
console.log(p.name);// sunny
var p1 = new Person();
console.log(p1.name);// cherry
// Person.prototype.name 是属性值的更改
// 而Person.prototype = {} 是Person中隐式的this里面__proto__ 属性引用的更改.引用更改了,但是p的引用指向还是原来的引用值,在生成的p1是新引用的产物
// 3.
var obj = {name : 'a'};
var obj1 = obj
obj = {name : 'b'};
console.log(obj.name); // b
console.log(obj1.name);// b
// ----
Person.prototype = {name : 'a'};
__proto__ = Person.prototype;
Person.prototyp = {name : 'b'};
// 4.
Person.prototype.name = 'sunny';
function Person() {
}
Person.prototype = {
name : 'cherry'
};
var p = new Person();
// 哈哈,改了两遍才new,new才生成this
console.log(p.name);// cherry
原型链
- 如何构成原型链
- 原型链上属性的增删改查
- 绝大多数对象的最终都会继承自Object.prototype
- Object.create(原型);
// 10. 原型链
// Grand.prototype.__protto__ = Object.prototype
Grand.prototype.lastName = 'Deng';
function Grand(){
}
var grand = new Grand();
Father.prototype = grand;
function Father() {
this.name = 'xuming';
}
var father = new Father();
Son.prototype = father;
function Son() {
this.hobbit = 'smoke';
}
var son = new Son();
console.log(son.hobbit);
console.log(son.name);
console.log(son.lastName);
// 1.
Grand.prototype.lastName = 'Deng';
function Grand(){
}
var grand = new Grand();
Father.prototype = grand;
function Father() {
this.name = 'xuming';
this.fortune = {
card1 : 'visa'
}
}
var father = new Father();
Son.prototype = father;
function Son() {
this.hobbit = 'smoke';
}
var son = new Son();
// son.fortune = 'one';
// console.log(son.fortune);
// console.log(son);
son.fortune.card2 = 'icbc';
console.log(son.fortune);
console.log(father);
// 2.
Grand.prototype.lastName = 'Deng';
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();
son.num ++ ;
console.log(father.num);// 100
console.log(son.num); // 101
// 11. 父类方法子类调用变量隶属问题
// 1.
Person.prototype = {
name : 'a',
sayName : function () {
console.log(this.name);
}
};
function Person() {
this.name = 'b'
}
var person = new Person();
person.sayName(); // a
// a.sayName() sayName里面的this指向是:谁调用的这个方法中,this就指向谁
// 2.
Person.prototype = {
name : 'a',
sayName : function () {
console.log(this.name);
}
};
function Person() {
this.name = 'b'
}
var person = new Person();
person.sayName(); // b
Person.prototype.sayName(); // a
// 12. 创建
// 自变量
var obj = {}; // -->new Object();
// 最好别用
var obj1 = new Object();
// var obj2 = Object.create(原型);
var Objj = {name : 'sunny', age : 123};
var obj3 = Object.create(Objj);
// 1.
// var obj = Object.create(原型) null/对象
Person.prototype.name = 'sunny';
function Person() {}
var person = Object.create(Person.prototype);
// 2.
// Object.create(原型); 创建出来的对象,没有继承Object.prototype
var obj = Object.create(null);
obj.toString(); // 报错
// 3. 自己设置__proto__
obj.__proto__ = {name : 'sunny'};
// 不存在继承
console.log(obj.name); // undefined
// undefined 和 null 为啥没有toString()方法
// 1. undefined 和 null 为原始值
// 2. undefined 和 null 没有包装类
// 3. undefined 和 null 没有原型
// ** 数字 有包装类哦
toString();
true.toString();
var num = 123;
num.toString();// 123
var obj = {};
obj.toString(); // "[object Object]"
// 对比返回值思考
// -- > new Number(num).toString();
// Number 中是有自己的prototype 他将Object中的prototype 进行了重写
// Number.prototype.toString = function () {};
// Number.prototype.__proto__ = Object.prototype
// 重写的
// Object.prototype.toString
// Number.prototype.toString
// Array.prototype.toString
// Boolean.prototype.toString
// String.prototype.toString
console.log(Object.prototype.toString.call(123))// [object Number]
// 衍生:重写
// 2. 重写
Person.prototype = {
toString : function () {
return 'chongxie'
}
};
function Person() {
}
var person = new Person();
console.log(person.toString());// chongxie
// 3. 重写Object内toString()
Object.prototype.toString = function () {
return 'Object chongxie';
}
function Person() {
}
var person = new Person();
console.log(person.toString());// Object chongxie
document.write()
var num = 123;
document.write(num); // 123
var obj = {};
document.write(obj); // [object Object]
var objC = Object.create(null);
document.write(objC);// 报错 document.write 调用的是原型中toString的方法
var obj1 = Object.create(null);
obj1.toString = function () {
return '测试是否调用toString()';
};
document.write(obj1);
call/apply
call和apply的相同点:改变this指向
改变this指向
call和apply的不同点:传参列表不同
- call 需要把实参按着形参的个数传进去
- apply 只能传一个arguments
// 方法调用 之call
function test() {
console.log('aa');
}
test.call();
test(); // 也可以这样执行 --> test.call();
// call 改变this指向
function Person(name, age) {
this.name = name;
this.age = age;
}
var person = new Person('yang', 100);
var obj = {};
console.log(person);
Person.call(obj, 'deng', 80); // 他会让Person中的this全部指向obj
console.log(obj); // {name: "deng", age: 80} 利用别人的额方法 实现了自己的功能
// Person 相当于工厂
// 应用
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
function Student(name, age, sex, tel, grade) {
// Person.call(Student, name, age, sex); 不对哦
Person.call(this, name, age, sex);
this.tel = tel;
this.grade = grade;
}
var student = new Student('sunny', 123, 'male', 139, 2017);
console.log(student);
function Wheel(wheelSize, style) {
this.style = style;
this.wheelSize = wheelSize;
}
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) {
Wheel.call(this, wheelSize, style);
Sit.call(this, c, sitColor);
Model.call(this, height, width, len);
}
function CarApply(wheelSize, style, c, sitColor, height, width, len) {
Wheel.apply(this, [wheelSize, style]);
Sit.apply(this, [c, sitColor]);
Model.apply(this, [height, width, len]);
}
var car = new Car(100, '漂亮', '真皮', 'red', 1000, 1000, 4000 );
var carApply = new CarApply(100, '漂亮', '真皮', 'red', 1000, 1000, 4000 );
console.log(car);
console.log(carApply);