原型链
- 每个函数对象有个一个
prototype
(显式原型),指向constructor
;但constructor.prototype
指向本身. - 实例只有
__proto__
(隐式原型) - 所有实例需要共享的属性和方法,都可放在
prototype
;不需要则放在构造函数中 - 实例的
__proto__
指向构造该对象的构造函数的原型即**.prototype
es5 6种继承
来自原型对象的引用属性是所有实例共享的
|
|
简单链
1234567Sub.prototype = new Super();//共享原型对象,arr是引用类型var sub1 = new Sub();var sub2 = new Sub();//1.无法构造函数传参sub1.val = 2;//不会影响sub2sub1.arr.push(2);//会影响sub2补充
对继承的简单链原理补充
我一直在想那样的影响为何有,今天想通了,来做点笔记补充:
- call: 替换上下文,可以想象成替换
this
- new:123var obj = {};obj.__proto__ = Base.prototype;Base.call(obj);
在
call
替换后,它还会再调用一遍Base
函数,保证有成员变量过程分析:
- 第一行的
new Super
直接导致Sub.prototype
拥有了val
和arr
- 二三行的
new Sub
只是将__proto__
指向了Sub.prototype
所以使用
sub.val
sub.arr
却也只是访问Sub.prototype
上面的东西而已如此说来,大家都访问一个东西却为何
val
不影响呢?
因为在第6行里是个创建而不是修改第六行是对
sub1
创建一个私有属性并赋值
第七行是访问sub1
的arr
,然而没有从原型链上拿去了- 简单链很好,就怕某地出错,记住它们是访问一个
- 借用构造函数这个太浪费了不考虑
- new的数量不是很多倒是可以用用组合继承
- call: 替换上下文,可以想象成替换
借用构造函数
12345function Super(val) {...}function Sub(val) {Super.call(this, val); //1.子类互不影响 2.但是复制了父类实例属性导致内存增加 3.call不会复制原型链}var sub1 = new Sub();组合继承
12345678function Super(val) {...}Super.prototype.fun1 = function(){};//函数全放入原型中,方便共享function Sub(val) {Super.call(this, val);//保留传参功能}Sub.prototype = new Super();//1. 函数复用 2.构造函数传参 3.原型多余内存var sub1 = new Sub(1);
寄生组合继承
1234567891011121314151617function Super(val) {...}Super.prototype.fun1 = function(){};function Sub(val) {Super.call(this, val);}function beget(obj) { //构建只有原型链的空对象var F = function() {};F.prototype = obj;return new F();}var proto = beget(Super.prototype);proto.constructor = Sub;Sub.prototype = proto;var sub = new Sub();//1.确实解决了以上所有问题 2.书写太麻烦了原型(感觉没意义)
123456789function beget(obj) {var F = function(){};F.prototype = obj;return new F();}var sup = new Super();var sub = beget(sup);sub.v = v;...
es6继承
上面的寄生组合继承
同,多个static
定义静态属性
Curry
这个概念是存储传入参数,够了才执行函数
123456let fun = a=> b=> c=> {return a+b+c}//注意returnlet fun1 = fun(1)//存储函数let fun2 = fun1(2);let fun3 = fun2(3);//6let fun1 = fun(1)(2)(3)//6, 参数多了会报错
compose
这个es6并没有实现,但是很多库有这个函数
12345var greeting = (firstName, lastName) => 'hello, ' + firstName + ' ' + lastNamevar toUpper = str => str.toUpperCase()var fn = compose(toUpper, greeting)console.log(fn('jack', 'smith'))// ‘HELLO,JACK SMITH’
- compose的参数是函数,返回的也是一个函数
- 因为除了第一个函数的接受参数,其他函数的接受参数都是上一个函数的返回值,所以初始函数的参数是多元的,而其他函数的接受值是一元的
- compsoe函数可以接受任意的参数,所有的参数都是函数,且执行方向是自右向左的,初始函数一定放到参数的最右面