一、原型


ptototype:构造函数的原型。
proto:实例化对象的一个属性,指向构造函数的原型ptototype。
实例化对象的proto属性指向构造函数的原型ptototype

  1. function Car() {}
  2. var car = new Car();
  3. console.log(Car.prototype);
  4. console.log(car);

image.png

  1. function Car() {
  2. this.a=1;
  3. }
  4. Car.prototype.name='benz'
  5. var car = new Car();
  6. car.color='red';
  7. console.log(Car.prototype);
  8. console.log(car);

image.png

  1. function Car() {
  2. this.a=1;
  3. }
  4. Car.prototype.name='benz'
  5. var car = new Car();
  6. car.color='red';
  7. console.log(Car.prototype);
  8. console.log(car);
  9. console.log(car.__proto__===Object)//false
  10. console.log(car.__proto__===Car.prototype)//true
  11. console.log(car.__proto__.__proto__===Object.__proto__)//false
  12. console.log(car.__proto__.__proto__===Object.prototype)//true
  13. console.log(car.__proto__.__proto__===Car.prototype.__proto__)//true
  14. console.log(car.__proto__.__proto__.__proto__)//null
  15. console.log(Object.prototype.prototype)//undefined
  16. console.log(Object.prototype.__proto__)//null
  17. 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

  1. // Professor原型上添加属性
  2. Professor.prototype.tSkill = "JAVA";
  3. function Professor() {this.p=1;}
  4. // 实例化一个Professor对象
  5. var professor = new Professor();
  6. console.log(professor)
  7. // Teacher构造函数原型指向professor对象
  8. Teacher.prototype = professor;
  9. function Teacher() {
  10. this.mSkill = "jS/JQ";
  11. }
  12. // 实例化一个Teacher对象
  13. var teacher = new Teacher();
  14. console.log(teacher)
  15. // Student构造函数原型指向teacher对象
  16. Student.prototype = teacher;
  17. console.log(teacher)
  18. function Student() {
  19. this.pSkill = "HTML/CSS";
  20. }
  21. // 实例化一个Student对象
  22. var student = new Student();
  23. console.log(student)
  24. console.log(Teacher.prototype===professor)
  25. //true 因为之前把Teacher.prototype指向professor


image.png

  1. // Professor原型上添加属性
  2. Professor.prototype.tSkill = 'JAVA';
  3. function Professor() {}
  4. // 实例化一个Professor对象
  5. var professor = new Professor();
  6. // Teacher构造函数原型指向professor对象
  7. Teacher.prototype = professor;
  8. function Teacher() {
  9. this.mSkill = 'jS/JQ';
  10. this.success = {
  11. alibaba: '28',
  12. tencent: '30'
  13. }
  14. this.students = 500;
  15. }
  16. // 实例化一个Teacher对象
  17. var teacher = new Teacher();
  18. // Student构造函数原型指向teacher对象
  19. Student.prototype = teacher;
  20. function Student() {
  21. this.pSkill = 'HTML/CSS';
  22. }
  23. // 实例化一个Student对象
  24. var student = new Student();
  25. /**
  26. * 1. student对象没有success属性,沿着原型链向上查找
  27. * 2. student.success = student.__proto__.success
  28. * 3. student.students.baidu = '100'
  29. * 4. student.success.alibaba = '29'
  30. success是引用值,可以增加、修改成功,在Teacher的原型上直接修改,可以修改,但不推荐修改原型上的值
  31. */
  32. student.success.baidu = '100';
  33. student.success.alibaba = '29';
  34. /**
  35. * 1. student对象没有students属性,沿着原型链向上查找
  36. * 2. student.students = student.__proto__.student
  37. * 3. student.students++
  38. students是原始值,不直接修改,会在student新建students属性,并把teacher的students属性赋值
  39. 因为不能修改原型上的值,所以会在studuent上新建students属性先赋值原型上studnets的值,再加一
  40. */
  41. student.students++;
  42. console.log(teacher, student);

image.png

访问对象的属性和方法时,优先访问自身的属性和方法,没有再按照原型链查找。

  1. function Car() {
  2. this.brand = 'Benz';
  3. }
  4. Car.prototype = {
  5. brand: 'Mazda',
  6. intro: function () {
  7. console.log('我是' + this.brand + '车');
  8. }
  9. }
  10. var car = new Car();
  11. car.intro(); // '我是Benz车'
  12. //this指向实例对象car,car最上面有 this.brand = 'Benz';
  13. Car.prototype.intro()//'我是Mazda车' this指向Car.prototype
  14. //------------------------------------------------------------------------------------------
  15. function Person() {
  16. this.smoke = function () {
  17. this.weight--;
  18. }
  19. }
  20. Person.prototype = {
  21. weight: 130
  22. }
  23. var person = new Person();
  24. person.smoke();//undefined 函数没写return返回undefined new函数返回this
  25. console.log(person);

image.png

三、对象继承

3.1 创建对象的方法


1.字面量
2.Object构造函数

  1. var obj1 = {}
  2. console.log(obj1);
  3. var obj2 = new Object(); // 一般不用
  4. console.log(obj2);
  5. function Obj() {}
  6. var obj3 = new Obj();
  7. console.log(obj3.__proto__ === Obj.prototype)//true

create

3、Object.create(proto) 指定对象的原型,当参数为 null 时可以创建出没有原型的对象。

  1. // 创建obj1空对象
  2. // 不是所有的对象都继承于Object.prototype
  3. var obj1 = Object.create(null);
  4. console.log(obj1);
  5. obj1.num = 1;
  6. var obj2 = Object.create(obj1);
  7. console.log(obj2);
  8. console.log(obj2.num);
  9. var obj = Object.create(null);
  10. obj.num = 1;
  11. var obj1 = {
  12. count: 2
  13. }
  14. obj.__proto__ = obj1;
  15. // 给空对象添加__proto__属性无效
  16. console.log(obj.count); // undefined

image.png

create放的是原型
函数 参数是什么类型 什么意思
返回值是什么类型 什么意思
obj1与obj2相等 一样

  1. function Obj() {}
  2. Obj.prototype.num = 1;
  3. var obj1 = Object.create(Obj.prototype);
  4. // 实例化obj2
  5. // 调用构造函数Obj原型上的属性和方法
  6. // 指定实例对象的原型
  7. var obj2 = new Obj();
  8. console.log(obj1);
  9. console.log(obj2);

create作用:自定义实例对象的原型,object.create(xx)相当于构造函数.原型=xx 再用构造函数new一个实例对象,就相当基础的写法

  1. var test={
  2. num=2
  3. }
  4. function Obj(){}
  5. obj.prototype.num=1;
  6. var obj1=Object.create(test);
  7. // 实例化obj2
  8. // 调用构造函数Obj原型上的属性和方法
  9. // 指定实例对象的原型
  10. var obj2=new Obj();
  11. console.log(obj1)
  12. console.log(obj2)

image.png
相当于新建构造函数obj1的实列对象obj2,相当于new构造函数
新建null对象,打印空 没有原型链
new新建实例对象包含create操作
image.png

image.png
错误 不继承object原型,没有tostring方法
image.png

image.png
image.png
系统内置是浅色的,自定义是深色的
image.png
undefined自己指定proto没用,得是系统指定才有用
系统内置你可以更改它,但不能自造它

四、toString方法

4.1 undefined、null没有属性和方法。

不能.toString,没有包装类,没有原型

  1. var num = 1;
  2. // 原始值没有属性和方法
  3. num.toString();
  4. // new Number(1) -> toString();
  5. var num2 = new Number(num);
  6. console.log(num2.toString());

image.pngNumber中重写了toString

4.2 document.write()会调用打印对象的toString方法。

隐式转换

  1. var num = 1;
  2. var obj = {};
  3. var obj2 = Object.create(null);
  4. document.write(num);
  5. document.write(obj);
  6. document.write(obj2); // TypeError: Cannot convert object to primitive value
  7. obj2.toString = function () {
  8. return 'sss'
  9. }
  10. document.write(obj2); // 'sss'

4.3 通过Object.prototype.toString方法判断对象类型。

  1. var toString = Object.prototype.toString;
  2. console.log(toString.call(1)); // [object Number]
  3. console.log(toString.call('a')); // [object String]
  4. console.log(toString.call(true)); // [object Boolean]
  5. console.log(toString.call([])); // [object Array]
  6. console.log(toString.call({})); // [object Object]

五、call、apply改变this指向

image.png

  1. function test(){
  2. console.log('a')
  3. }
  4. test()
  5. test.call()
  6. test.call(window)

全是a,不光结果一样,效果意思也一样默认的this是window,this是返回的对象
其实test()默认在test之后加上.call,其实test()相当于test.call()

  1. function test(){
  2. this.n=1;
  3. console.log('a')
  4. }
  5. test()
  6. // test.call()
  7. // test.call(window)
  8. console.log(n)//1 弄到window中
  1. function Car(brand,color){
  2. this.brand=brand;
  3. this.color = color;
  4. }
  5. var newCar={}
  6. Car.call(newCar,'Benz','red')
  7. console.log(newCar)

image.png
相当于把this对象变成newCar对象
image.png

  1. function Car(brand,color){
  2. newCar.brand=brand;
  3. newCar.color = color;
  4. }
  5. var newCar={}
  6. // Car.call(newCar,'Benz','red')
  7. Car('Benz','red')
  8. console.log(newCar)

image.png

  1. function Car(brand, color) {
  2. this.brand = brand;
  3. this.color = color;
  4. this.run = function () {
  5. console.log('running');
  6. }
  7. }
  8. var newCar = {
  9. displacement: '3.0'
  10. };
  11. // Car.call(newCar, 'Benz', 'red');
  12. Car.apply(newCar, ['Benz', 'red']);
  13. console.log(newCar);
  14. var car = new Car('Benz', 'red');
  15. console.log(car);

image.png

使用call、apply借用其它对象的属性和方法。

  1. function Compute() {
  2. this.plus = function (a, b) {
  3. console.log(a + b);
  4. }
  5. this.minus = function (a, b) {
  6. console.log(a - b);
  7. }
  8. }
  9. function FullCompute() {
  10. // Compute.call(this); //与apply一样
  11. Compute.apply(this);
  12. this.mul = function (a, b) {
  13. console.log(a * b);
  14. }
  15. this.div = function (a, b) {
  16. console.log(a / b);
  17. }
  18. }
  19. var compute = new FullCompute();
  20. /*上面的this指的是FullCompute的实例对象,首先运行实例对象compute.plus、compute.minus
  21. 之后运行实例对象compute.mul、compute.div,本来是this.mul等,但这里this就是实例对象
  22. Compute.apply(this)等函数运行、实例化时运行,但也可以看作,把Compute的this的内容,添加到FullCompute中
  23. */
  24. compute.plus(1, 2);
  25. compute.minus(1, 2);
  26. compute.mul(1, 2);
  27. compute.div(1, 2);

六、作业

年龄为多少岁,姓名为xx买了一辆排量为XX的什么颜色的什么牌子的车 call apply。

  1. function Car(opt) {
  2. this.displacement = opt.displacement;
  3. this.color = opt.color;
  4. this.brand = opt.brand;
  5. }
  6. function Person(opt) {
  7. this.name = opt.name;
  8. this.age = opt.age;
  9. Car.call(this, {
  10. displacement: opt.displacement,
  11. color: opt.color,
  12. brand: opt.brand
  13. });
  14. console.log('姓名为' + this.name + '年龄为' + this.age + '买了一辆排量为' + this.displacement + '的' + this.color + '色的' + this.brand + '牌的车');
  15. }
  16. var person = new Person({
  17. name: '张三',
  18. age: '24',
  19. color: 'red',
  20. displacement: '100',
  21. brand: 'Benz'
  22. })

返回什么返回的是对象,构造函数返回的是对象this,也有返回值

  1. function Car(opt) {
  2. this.displacement = opt.displacement;
  3. this.color = opt.color;
  4. this.brand = opt.brand;
  5. }
  6. function Person(opt) {
  7. this.age = opt.age;
  8. this.name = opt.name;
  9. Car.call(this, opt)
  10. }
  11. var person = new Person({
  12. name: '张三',
  13. age: '24',
  14. color: 'red',
  15. displacement: '100',
  16. brand: 'Benz'
  17. })
  18. console.log(person)

image.png

  1. function Car(opt) {
  2. this.displacement = opt.displacement;
  3. this.color = opt.color;
  4. this.brand = opt.brand;
  5. }
  6. function Person(opt) {
  7. this.age = opt.age;
  8. this.name = opt.name;
  9. // this.car = {};
  10. Car.call(this.car={}, opt.car)//必须={}初始化
  11. }
  12. var person = new Person({
  13. name: '张三',
  14. age: '24',
  15. car:{
  16. color: 'red',
  17. displacement: '100',
  18. brand: 'Benz'
  19. }
  20. })
  21. console.log(person)

image.png