一、原型的深入
prototype:构造函数的原型
__proto__:实例化对象的一个属性,指向构造函数的原型
所有对象都有原型,包括原型本身
function Car() {}
var car = new Car();
console.log(Car.prototype);
console.log(car);
二、原型链
1.
实例化对象通过__proto__属性向上查找属性和方法的链条就叫做原型链。
原型链的顶端是Object.prototype,它有一个内置的to String方法。
// Professor原型上添加属性
Professor.prototype.tSkill = 'JAVA';
function Professor() {}
// 实例化一个Professor对象
var professor = new Professor();
// Teacher构造函数原型指向professor对象
Teacher.prototype = professor;
function Teacher() {
this.mSkill = 'jS/JQ';
this.success = {
alibaba: '28',
tencent: '30'
}
this.students = 500;
}
// 实例化一个Teacher对象
var teacher = new Teacher();
// Student构造函数原型指向teacher对象
Student.prototype = teacher;
function Student() {
this.pSkill = 'HTML/CSS';
}
// 实例化一个Student对象
var student = new Student();
/**
* 1. student对象没有success属性,沿着原型链向上查找
* 2. student.success = student.__proto__.success
* 3. student.students.baidu = '100'
* 4. student.success.alibaba = '29'
*/
student.success.baidu = '100';
student.success.alibaba = '29';
/**
* 1. student对象没有students属性,沿着原型链向上查找
* 2. student.students = student.__proto__.student
* 3. student.students++
*/
student.students++;
console.log(teacher, student);
注意: 对于原始值,student对象是在链条上找student属性,然后找到了就拿到这个值,进行操作后,在自己这个对象中创建这个属性,保存。所以说不会改变链条上的teacher这个对象中student这个属性的值,引用值就会改变。
2.
访问对象的方法和属性时,优先访问自身的属性和方法,没有就去原型上找。
function Car() {
this.brand = 'Benz';
}
Car.prototype = {
brand: 'Mazda',
intro: function () {
console.log('我是' + this.brand + '车');
}
}
var car = new Car();
car.intro(); // '我是Benz车'
Car.prototype.intro(); //'我是Mazda车'
//------------------------------------------------------------------------------------------
function Person() {
this.smoke = function () {
this.weight--;
}
}
Person.prototype = {
weight: 130
}
var person = new Person();
person.smoke();
console.log(person);
注意:谁调用,this指向谁,第一个是car调用,所以this是car,打印car中的brand。第二个是原型调用,所以打印原型上的。
函数默认返回undefind,构造函数默认是this。返回值可以更改,构造函数只有返回引用值才会有效,原始值还是默认返回this。
三、对象继承
1. 创建对象
var obj1 = {}
console.log(obj1);
var obj2 = new Object(); // 一般不用
console.log(obj2);
function Obj() {}
var obj3 = new Obj();
console.log(obj3.__proto__ === Obj.prototype)
2. Object.create构建对象
Object.create(proto)指定对象的原型,当参数为null时可以创建出没有原型的对象,
所以说不是所有对象都有原型。
function Obj(){}
Obj.prototype.num=1;
var obj1=Object.create(Obj.prototype);
var obj2=new Obj();
console.log(obj1);
console.log(obj2);
// 创建obj1空对象
// 不是所有的对象都继承于Object.prototype
var obj1 = Object.create(null);
console.log(obj1);
obj1.num = 1;
var obj2 = Object.create(obj1);
console.log(obj2);
console.log(obj2.num);
var obj = Object.create(null);
obj.num = 1;
var obj1 = {
count: 2
}
obj.__proto__ = obj1;
// 给空对象添加__proto__属性无效
console.log(obj.count); // undefined
注意:proto是系统自带的属性,你可以重写,更改,但是不能自己造出来,就是var obj = Object.create(null);他没有proto这个属性,你造出来也没有继承的作用。
四、toSting方法
1. 原始值、undefind、null没有属性和方法,它们也没有原型。但是原始值可以通过包装类变成一个对象,然后使用这个方法。
var num = 1;
// 原始值没有属性和方法
num.toString();
// new Number(1) -> toString();
var num2 = new Number(num);
console.log(num2.toString());
2. 原型的原型上有一个自带的toSting方法
3. document.write()会调用打印对象的toString方法。
五、call、apply
1. 系统会隐式添加一个call
function test(){
console.log('a');
}
test.call();
2. 改变this指向
function Car(brand, color) {
this.brand = brand;
this.color = color;
this.run = function () {
console.log('running');
}
}
var newCar = {
displacement: '3.0'
};
// Car.call(newCar, 'Benz', 'red');
Car.apply(newCar, ['Benz', 'red']);
console.log(newCar);
var car = new Car('Benz', 'red');
console.log(car);
call、apply区别就是传入的参数,call是参数,apply是数组,arguments
案例
function Compute() {
this.plus = function (a, b) {
console.log(a + b);
}
this.minus = function (a, b) {
console.log(a - b);
}
}
function FullCompute() {
Compute.apply(this);
this.mul = function (a, b) {
console.log(a * b);
}
this.div = function (a, b) {
console.log(a / b);
}
}
var compute = new FullCompute();
compute.plus(1, 2);
compute.minus(1, 2);
compute.mul(1, 2);
compute.div(1, 2);
六、作业
年龄为多少岁,姓名为xx买了一辆排量为XX的什么颜色的什么牌子的车 call 、apply。
function Car(opt) {
this.displacement = opt.displacement;
this.color = opt.color;
this.brand = opt.brand;
}
function Person(opt) {
this.name = opt.name;
this.age = opt.age;
Car.call(this, {
displacement: opt.displacement,
color: opt.color,
brand: opt.brand
});
console.log('姓名为' + this.name + '年龄为' + this.age + '买了一辆排量为' + this.displacement + '的' + this.color + '色的' + this.brand + '牌的车');
}
var person = new Person({
name: '张三',
age: '24',
color: 'red',
displacement: '100',
brand: 'Benz'
})