一、原型
ptototype:构造函数的原型。
proto:实例化对象的一个属性,指向构造函数的原型ptototype。
实例化对象的proto属性指向构造函数的原型ptototype
function Car() {}
var car = new Car();
console.log(Car.prototype);
console.log(car);
function Car() {
this.a=1;
}
Car.prototype.name='benz'
var car = new Car();
car.color='red';
console.log(Car.prototype);
console.log(car);
function Car() {
this.a=1;
}
Car.prototype.name='benz'
var car = new Car();
car.color='red';
console.log(Car.prototype);
console.log(car);
console.log(car.__proto__===Object)//false
console.log(car.__proto__===Car.prototype)//true
console.log(car.__proto__.__proto__===Object.__proto__)//false
console.log(car.__proto__.__proto__===Object.prototype)//true
console.log(car.__proto__.__proto__===Car.prototype.__proto__)//true
console.log(car.__proto__.__proto__.__proto__)//null
console.log(Object.prototype.prototype)//undefined
console.log(Object.prototype.__proto__)//null
console.log(car.prototype)//undefined
实例对象car->Car.prototype->Object.prototype 得实例对象先指向原型,实例对象是第一个,它自身的原型是第二个
实例对象没有prototype属性,只有proto属性
原型中也有原型prototype,但不能.prototype,需要.proto
原型链指向构造函数的原型,不指向构造函数,叫原型链肯定与原型有关,都指向原型
二、原型链
从上往下继承,
实例化对象通过 proto 属性向上查找属性和方法的链条就叫做原型链。
原型链的顶端是 Object.prototype。
student实例对象->Student.prototype->Teacher.prototype->Professor.prototype->Object.prototype
不是student实例对象->实例对象teacher对象->professor对象->Professor.prototype->Object.prototype
Teacher.prototype与之前的Car.prototype有区别,因为把Teacher.prototype的指向改变了,变成了实例对象,Teacher.prototype.proto不会是Object.prototype了,而是实例对象对应构造函数的prototype
// Professor原型上添加属性
Professor.prototype.tSkill = "JAVA";
function Professor() {this.p=1;}
// 实例化一个Professor对象
var professor = new Professor();
console.log(professor)
// Teacher构造函数原型指向professor对象
Teacher.prototype = professor;
function Teacher() {
this.mSkill = "jS/JQ";
}
// 实例化一个Teacher对象
var teacher = new Teacher();
console.log(teacher)
// Student构造函数原型指向teacher对象
Student.prototype = teacher;
console.log(teacher)
function Student() {
this.pSkill = "HTML/CSS";
}
// 实例化一个Student对象
var student = new Student();
console.log(student)
console.log(Teacher.prototype===professor)
//true 因为之前把Teacher.prototype指向professor
// 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'
success是引用值,可以增加、修改成功,在Teacher的原型上直接修改,可以修改,但不推荐修改原型上的值
*/
student.success.baidu = '100';
student.success.alibaba = '29';
/**
* 1. student对象没有students属性,沿着原型链向上查找
* 2. student.students = student.__proto__.student
* 3. student.students++
students是原始值,不直接修改,会在student新建students属性,并把teacher的students属性赋值
因为不能修改原型上的值,所以会在studuent上新建students属性先赋值原型上studnets的值,再加一
*/
student.students++;
console.log(teacher, student);
访问对象的属性和方法时,优先访问自身的属性和方法,没有再按照原型链查找。
function Car() {
this.brand = 'Benz';
}
Car.prototype = {
brand: 'Mazda',
intro: function () {
console.log('我是' + this.brand + '车');
}
}
var car = new Car();
car.intro(); // '我是Benz车'
//this指向实例对象car,car最上面有 this.brand = 'Benz';
Car.prototype.intro()//'我是Mazda车' this指向Car.prototype
//------------------------------------------------------------------------------------------
function Person() {
this.smoke = function () {
this.weight--;
}
}
Person.prototype = {
weight: 130
}
var person = new Person();
person.smoke();//undefined 函数没写return返回undefined new函数返回this
console.log(person);
三、对象继承
3.1 创建对象的方法
1.字面量
2.Object构造函数
var obj1 = {}
console.log(obj1);
var obj2 = new Object(); // 一般不用
console.log(obj2);
function Obj() {}
var obj3 = new Obj();
console.log(obj3.__proto__ === Obj.prototype)//true
create
3、Object.create(proto) 指定对象的原型,当参数为 null 时可以创建出没有原型的对象。
// 创建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
create放的是原型
函数 参数是什么类型 什么意思
返回值是什么类型 什么意思
obj1与obj2相等 一样
function Obj() {}
Obj.prototype.num = 1;
var obj1 = Object.create(Obj.prototype);
// 实例化obj2
// 调用构造函数Obj原型上的属性和方法
// 指定实例对象的原型
var obj2 = new Obj();
console.log(obj1);
console.log(obj2);
create作用:自定义实例对象的原型,object.create(xx)相当于构造函数.原型=xx 再用构造函数new一个实例对象,就相当基础的写法
var test={
num=2
}
function Obj(){}
obj.prototype.num=1;
var obj1=Object.create(test);
// 实例化obj2
// 调用构造函数Obj原型上的属性和方法
// 指定实例对象的原型
var obj2=new Obj();
console.log(obj1)
console.log(obj2)
相当于新建构造函数obj1的实列对象obj2,相当于new构造函数
新建null对象,打印空 没有原型链
new新建实例对象包含create操作
错误 不继承object原型,没有tostring方法
系统内置是浅色的,自定义是深色的
undefined自己指定proto没用,得是系统指定才有用
系统内置你可以更改它,但不能自造它
四、toString方法
4.1 undefined、null没有属性和方法。
不能.toString,没有包装类,没有原型
var num = 1;
// 原始值没有属性和方法
num.toString();
// new Number(1) -> toString();
var num2 = new Number(num);
console.log(num2.toString());
4.2 document.write()会调用打印对象的toString方法。
隐式转换
var num = 1;
var obj = {};
var obj2 = Object.create(null);
document.write(num);
document.write(obj);
document.write(obj2); // TypeError: Cannot convert object to primitive value
obj2.toString = function () {
return 'sss'
}
document.write(obj2); // 'sss'
4.3 通过Object.prototype.toString方法判断对象类型。
var toString = Object.prototype.toString;
console.log(toString.call(1)); // [object Number]
console.log(toString.call('a')); // [object String]
console.log(toString.call(true)); // [object Boolean]
console.log(toString.call([])); // [object Array]
console.log(toString.call({})); // [object Object]
五、call、apply改变this指向
function test(){
console.log('a')
}
test()
test.call()
test.call(window)
全是a,不光结果一样,效果意思也一样默认的this是window,this是返回的对象
其实test()默认在test之后加上.call,其实test()相当于test.call()
function test(){
this.n=1;
console.log('a')
}
test()
// test.call()
// test.call(window)
console.log(n)//1 弄到window中
function Car(brand,color){
this.brand=brand;
this.color = color;
}
var newCar={}
Car.call(newCar,'Benz','red')
console.log(newCar)
相当于把this对象变成newCar对象
function Car(brand,color){
newCar.brand=brand;
newCar.color = color;
}
var newCar={}
// Car.call(newCar,'Benz','red')
Car('Benz','red')
console.log(newCar)
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借用其它对象的属性和方法。
function Compute() {
this.plus = function (a, b) {
console.log(a + b);
}
this.minus = function (a, b) {
console.log(a - b);
}
}
function FullCompute() {
// Compute.call(this); //与apply一样
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();
/*上面的this指的是FullCompute的实例对象,首先运行实例对象compute.plus、compute.minus
之后运行实例对象compute.mul、compute.div,本来是this.mul等,但这里this就是实例对象
Compute.apply(this)等函数运行、实例化时运行,但也可以看作,把Compute的this的内容,添加到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'
})
返回什么返回的是对象,构造函数返回的是对象this,也有返回值
function Car(opt) {
this.displacement = opt.displacement;
this.color = opt.color;
this.brand = opt.brand;
}
function Person(opt) {
this.age = opt.age;
this.name = opt.name;
Car.call(this, opt)
}
var person = new Person({
name: '张三',
age: '24',
color: 'red',
displacement: '100',
brand: 'Benz'
})
console.log(person)
function Car(opt) {
this.displacement = opt.displacement;
this.color = opt.color;
this.brand = opt.brand;
}
function Person(opt) {
this.age = opt.age;
this.name = opt.name;
// this.car = {};
Car.call(this.car={}, opt.car)//必须={}初始化
}
var person = new Person({
name: '张三',
age: '24',
car:{
color: 'red',
displacement: '100',
brand: 'Benz'
}
})
console.log(person)