编程语言的佛魔道
流派
面向对象
总所周知的Java 一切皆对象(一不自觉我就想到think in java里的特别形象的灯泡图,真的是秒懂什么是方法什么是类)
什么是类(同一事物的抽象描述)
对象(实例)
封装
继承
多态
反射
函数式
JavaScript
算子
lamda
柯里化
高阶函数
纯函数
所以这就好比佛教和道教,每个流派都有自己的信仰。所以说编程语言上升到宗教层面还是挺可怕的
如果说上面不好理解,可以说说军队,武警和解放军虽然都是国防力量,但是性质不一样,一个对内(处突维稳,抢险救灾)一个对外(抵抗外敌)
所以说不能拿java特有的东西去看待js
JS之假继承
ES6新特性class出来之前 JS是没有继承的(都是模拟的)
JS有原型「prototype」共有属性
1 2 3 4 5 6 var a = new Object() // a可以调用toString() a.toString() //我们知道 a.__proto__ = Object.prototype Object.prototype 上有toString()
1 2 3 4 5 6 7 8 9 // Object是所有对象的基类 var a = new Array() a.valueOf() //a自己没有valueOf() //Array的原型没有valueOf() Array.__proto__ = Array.prototype //Object的原型有valueOf() 二次的原型查找 Array.__proto__.__proto__ = Object.prototype
JS是没有类的概念的,只有原型
但是面试官认为是有的。。。(因为人都会拿相似的东西去推测没接深入触过的东西)
什么是类
能产生对象的东西就是「类」
非常纯粹的人类对象
1 2 3 function Human(){} var person = new Human() // person就是一个对象了
人类应该有个名字
1 2 3 4 5 function Human(name){ this.name = name } var person = new Human('aa') person.name // aa
人类应该有些技能比如 跑
1 2 3 4 5 6 7 8 9 function Human(name){ this.name = name } Human.prototype.run = function(){ console.log('run') } var person = new Human('aa') person.name // aa person.run() // run
人类还有子类 比如 男人
1 2 3 4 5 6 7 8 // 男人类 他有一个属性就是性别 function Man(name){ this.gender = '男' } // 男人天生会打架 Man.prototype.fight = function(){ console.log('糊你熊脸') }
我们希望 Man 应该有个名字
1 2 3 4 5 6 7 8 9 10 11 12 13 //人类 function Human(name){ this.name = name } // 男人类 他有一个属性就是性别 function Man(name){ Human.call(this,name) this.gender = '男' } // 男人天生会打架 Man.prototype.fight = function(){ console.log('糊你熊脸') }
我们希望 Man 会跑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 //人类 function Human(name){ this.name = name } Human.prototype.run = function(){ console.log('run') } // 男人类 他有一个属性就是性别 function Man(name){ Human.call(this,name) this.gender = '男' } // 男人天生会打架 Man.prototype.fight = function(){ console.log('糊你熊脸') } Man.prototype.__proto__ = Human.prototype; //然后你声明一个 m1 var m1 = new Man('m1') m1.__proto__ = Man.prototype m1.__proto__.__proto__ = Human.prototype m1.__proto__.__proto__.__proto__ = Object.prototype
以上就是一个ES5完整的继承
核心只有两句话
1 2 Human.call(this,name) Man.prototype.__proto__ = Human.prototype;
但是IE里不允许你操作「下划线proto下划线」 我们可以像这样来模拟继承
1 Man.prototype = new Human()
虽然 new Human()产生的对象的
但是这样 new Human( )会产生一个对象 假设为temp
temp会自带一个name属性 这个是我们不想要的
我们只想要Human的原型上的东西
于是我们用这三句代替
1 2 3 4 5 6 7 8 //step1声明一个空函数,里面什么属性也没有 var f = function(){} //step2 让空函数「f」原型 = Human.prototype f.prototype = Human.prototype //step3 生成一个「f」对象因为它是个空函数 Man.prototype = new f()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function Human(name){ this.name = name } Human.prototype.run = function(){ console.log("我叫"+this.name+",我在跑") return undefined } function Man(name){ Human.call(this, name) this.gender = '男' } var f = function(){} f.prototype = Human.prototype Man.prototype = new f() Man.prototype.fight = function(){ console.log('糊你熊脸') }
ES6诞生了 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Human{ constructor(name){ this.name = name } run(){ console.log("我叫"+this.name+",我在跑") return undefined } } class Man extends Human{ constructor(name){ super(name) this.gender = '男' } fight(){ console.log('糊你熊脸') } }
extends就是为了连接原型链
1 2 Man extends Human 就是为了实现 Man.prototype.__proto__ = Human.prototype
1 super(name) 就是Human.call(this,name)
题外话
ES5方式的继承印证了,我对JS内存的理解
ES6方式你可以自行去浏览器里打印,你会发现它还是用的prototype实现继承的
也就是说ES6的继承会翻译成ES5的写法,如果你是Js程序员应该用ES5的写法,ES6是方便java程序员的写法。
如果你想给 Human 的原型添加一个种族是 人类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // ES5 Human.prototype.s = '人类' // ES6 对不起,不支持,有一种变通的写法 class Human{ constructor(name){ this.name = name } //麻烦不???? //麻烦不???? //麻烦不???? get s(){ return '人类' } run(){ console.log("我叫"+this.name+",我在跑") return undefined } }
ES5写法证明你是JS程序员
ES6写法证明你是Java程序员