原型

image.png

  1. //new Function() /*所有函数都是通过new Function构造出来的,所以函数也是实例对象,由Function创建出来的实例对象*/
  2. // function Foo(){
  3. // }
  4. var Foo=new Function();//与上面function Foo意思一样
  5. var foo=new Foo();
  6. console.log(Foo.__proto__===Function.prototype);//true Foo对象是谁构造出来的,Function
  7. console.log(Object.__proto__===Function.prototype);//true
  8. console.log(foo.__proto__===Foo.prototype);//true
  9. console.log(Foo.__proto__===Foo.prototype)//false

访问原型的方式有两种:
1.实例对象.proto
2.构造函数.prototype
实例对象.proto===生成此实例对象的构造函数.prototype
构造函数.prototype,也是一个对象

构造函数也是函数,都是一样的声明方式
函数也是对象,都是new Function创建出来的实例对象,对象就是实例对象

  1. const sum = new Function('a', 'b', 'return a + b');
  2. console.log(sum(2, 6));
  3. // expected output: 8
  1. console.log(Object.__proto__===Function.prototype);//true
  2. //var obj=new Object();
  3. /*Object可以new出来,Object也是构造函数,也是函数,函数也是对象,Object是默认的构造函数
  4. Function可以创建函数,构造函数,可以创建构造函数的构造函数,可以创建实例对象的实例对象
  5. 相当于Object实例对象.__proto__与生成Object实例对象的构造函数Function相等,
  6. 证明Function是Object实例对象的构造函数*/

Function创建的实例对象还是构造函数,Object不行,创建的是对象

  1. // var foo=new Foo();
  2. // new foo()//错误
  3. // var obj=new Object();
  4. // new obj()//错误
  5. var func=new Function();
  6. console.log(new func());//{}

Constructor

constructor是原型上才有的属性,它指向的是对应实例的构造器

  1. console.log(Function.prototype.constructor === Function);//true
  2. console.log(Function.prototype.constructor === Object);//flase
  3. console.log(Object.prototype.constructor===Object)//true
  4. console.log(Object.prototype);
  5. console.log(Object.constructor === Function);//true
  6. /*因为只有prototype中才有原型,所以Object没有原型,Object.操作是把Object当成是一个对象来操作,*/
  7. console.log(Object.__proto__.constructor === Function)//true

因为只有prototype中才有原型,所以Object没有原型,Object.操作是把Object当成是一个对象来操作,找Object对象中有没有constructor属性,但Object上没有,所以查找原型链上有没有,Object.proto就是Function.prototype,所以就变成了Function.prototype.constructor===Function,就是Object.proto.constructor === Function

就是实例对象.constructor===构造实例对象的构造函数

  1. function Foo() {}
  2. var foo=new Foo();
  3. console.log(foo.constructor===Foo);//true
  4. console.log(foo.__proto__.constructor === Foo)//true
  5. console.log(foo.prototype.constructor===Foo)

不是函数没有constructor,不能.prototype
image.png

  1. function Foo() {}
  2. console.log(Foo.__proto__)//Function构造函数

image.png
内置函数,打印看不见

  1. function Foo() {}
  2. var foo=new Foo();
  3. console.log(Function.__proto__===Function.prototype);//true
  4. console.log(foo.__proto__===Foo.prototype);//true

Function是实例对象,同时Function也是构造函数

  1. console.log(Function.prototype.__proto__===Object.prototype);//true

Function.prototype是对象.proto===构造函数Object.prototype

  1. console.log(typeof Object);//function
  2. console.log(typeof Function);//function
  1. console.log(Object.prototype);//原型的终点
  2. console.log(Object.prototype.__proto__);//null

为什么是null,不是undefined? 因为b未定义,未赋值undefined,如下

  1. var obj={
  2. a:1
  3. }
  4. console.log(obj.b)//undefined
  5. var c;
  6. console.log(c)//undefined

proto定义了,并且赋值了,为null

  1. var c=null;
  2. console.log(c)
  1. var c=null;
  2. console.log(c)//null

通过get、set方法赋值

  1. var t=null;
  2. t=setInterval(function() {
  3. },1000);
  4. var obj={
  5. a:1,
  6. get b(){
  7. return 2;
  8. }
  9. }
  10. console.log(obj.b)//2
  1. console.log(Object.__proto__===Function.prototype);//true
  2. console.log(Object.__proto__===Object.prototype)//false

只有Function既是函数,又是对象,相等其它的都像Object一样不相等,Object也是既是函数又是对象,只要是函数都是既是函数又是对象,但对象不一定是函数

  1. console.log(Function.prototype.__proto__===Object.prototype);//true Object.prototype是原型链的终点

原型链继承

原型继承实例对象

image.png
原型链继承 引用值共享的问题

Call继承:借用构造函数

  1. function Super(){
  2. this.a=[1,2,3,4];
  3. }
  4. Super.prototype.say=function() {
  5. console.log(1);
  6. }
  7. function Sub() {
  8. // Super.call(this);
  9. }
  10. Sub.prototype=new Super()
  11. var sub1=new Sub();
  12. var sub2 = new Sub();
  13. // sub1.a='3333';//不会影响
  14. sub1.a.push(5);
  15. console.log(sub1.a);
  16. console.log(sub2.a);

image.png
解决方法:借用构造函数
image.png

  1. function Super(){
  2. this.a=[1,2,3,4];
  3. }
  4. Super.prototype.say=function() {
  5. console.log(1);
  6. }
  7. function Sub() {
  8. Super.call(this);
  9. }
  10. // Sub.prototype=new Super()
  11. var sub1=new Sub();
  12. var sub2 = new Sub();
  13. sub1.a.push(5);
  14. console.log(sub1.a);
  15. console.log(sub2.a);

image.png
但是会出现,父类原型方法无法获取的问题

组合继承

红宝书上的(伪经典继承)

  1. function Super(){
  2. this.a=[1,2,3,4];
  3. }
  4. Super.prototype.say=function() {
  5. console.log(1);
  6. }
  7. function Sub() {
  8. Super.call(this);
  9. }
  10. Sub.prototype=new Super()
  11. var sub1=new Sub();
  12. var sub2 = new Sub();
  13. sub1.a.push(5);
  14. console.log(sub1.a);
  15. console.log(sub2.a);

image.png
create一句顶三句

经典继承

寄生组合继承
也不是很好的解决父原型上的继承;
YUI雅虎就是这么写的

  1. function Super(){
  2. this.a=[1,2,3,4];
  3. }
  4. Super.prototype.say=function() {
  5. console.log(1);
  6. }
  7. function Sub() {
  8. Super.call(this);
  9. }
  10. // Sub.prototype=new Super()
  11. sub.prototype=Object.create(Super.prototype);//比new Super()没有this.a的参与,this.a在Super.call(this);参与
  12. //sub.prototype.__proto__=Super.prototype;//相当于
  13. //Object.getPrototypeOf(Sub.prototype)=Sub.prototype; //错误
  14. var sub1=new Sub();
  15. var sub2 = new Sub();
  16. // sub1.a.push(5);
  17. // sub1.a='3333';
  18. console.log(sub1.a);
  19. console.log(sub2.a);
  20. sub1.say();//1
  21. sub2.say();//1
  1. function Super() {
  2. this.a = [1, 2, 3, 4];
  3. }
  4. Super.prototype.say = function () {
  5. console.log(1);
  6. }
  7. function Sub() {
  8. Super.call(this);
  9. }
  10. // Sub.prototype=new Super()
  11. // Sub.prototype=Object.create(Super.prototype);
  12. // Object.getPrototypeOf(Sub.prototype)=Sub.prototype;
  13. // sub.prototype.__proto__=Super.prototype;
  14. //es版本低,没有Object.create方法
  15. if (!Object.create) {
  16. Object.create = function (proto) {
  17. var F = function () { };
  18. F.prototype = proto;
  19. return new F();
  20. }
  21. }
  22. Sub.prototype.say2 = function () {
  23. console.log(333333);
  24. }//会被Sub.prototype = Object.create(Super.prototype);所覆盖,得不到应用
  25. Sub.prototype = Object.create(Super.prototype);
  26. Sub.prototype.say2 = function () {
  27. console.log(333333);
  28. }
  29. var sub1 = new Sub();
  30. var sub2 = new Sub();
  31. // sub1.a.push(5);
  32. // sub1.a='3333';
  33. console.log(sub1.a);
  34. console.log(sub2.a);
  35. sub1.say();
  36. sub2.say();
  37. sub1.say2();

圣杯继承

圣杯模式也是重写了原型,重新覆盖了原型,也是之前写的得不到应用

class继承

比较好,es6方式是最完美的解决方式
许多框架用的别的,还有更多的继承方式
如拷贝继承用的人很少

  1. class Super{
  2. constructor() {
  3. this.a=[1,2,3,4];
  4. }
  5. say2(){
  6. console.log(22222);
  7. }
  8. }
  9. class Sub extends Super {
  10. say1() {
  11. console.log('1111111');
  12. }
  13. }
  14. var sub1=new Sub();
  15. var sub2=new Sub();
  16. // sub1.a='3333';
  17. console.log(sub1.a);
  18. console.log(sub2.a);
  19. sub1.say1();
  20. sub1.say2();

image.png

私有成员es7

  1. class Super{
  2. //a=[1,2,3,4];
  3. constructor() {
  4. this.a=[1,2,3,4];
  5. }
  6. say2(){
  7. console.log(22222);
  8. }
  9. }
  10. class Sub extends Super {
  11. // b=[5,6,7,8];
  12. //相当于 私有成员变量 成员属性
  13. constructor(){
  14. super();
  15. this.b=[5,6,7,8];
  16. }
  17. say1() {
  18. console.log('1111111');
  19. }
  20. }
  21. var sub1=new Sub();
  22. var sub2=new Sub();
  23. // sub1.a='3333';
  24. console.log(sub1.b);
  25. console.log(sub2.a);
  26. // sub1.say1();
  27. // sub1.say2();

image.png

  1. class Super {
  2. constructor () {
  3. this.a = [1, 2, 3, 4];
  4. }
  5. say2() {
  6. console.log(22222);
  7. }
  8. }
  9. class Sub extends Super {
  10. // b=[5,6,7,8];
  11. //相当于 私有成员变量
  12. constructor () {
  13. super();
  14. this.b = [5, 6, 7, 8];
  15. }
  16. say() {
  17. console.log('prototype');
  18. }
  19. static say1() {
  20. console.log('static');
  21. }
  22. }
  23. //相当于如下,
  24. var sub1 = new Sub();
  25. var sub2 = new Sub();
  26. // sub1.a='3333';
  27. console.log(sub1.b);
  28. // console.log(sub2.a);
  29. sub1.say();
  30. Sub.say1();

image.png
相当于

  1. function Sub() {
  2. this.a = [1,2,3];
  3. }
  4. Sub.prototype={
  5. say:function() {
  6. console.log('prototype')
  7. }
  8. }
  9. Sub.say1=function() {
  10. console.log('static')
  11. }
  12. var sub1=new Sub()
  13. sub1.say();
  14. Sub.say1();

image.png
静态方法

  1. Object.getPrototypeOf();
  2. Array.from();
  3. [].sort();
  4. [].indexOf();