一、继承
通过 new 实例化出来的对象继承构造函数的原型。
function Person() {}Person.prototype.name = 'Lucy';var p = new Person();console.log(p);

通过更改构造函数 prototype 属性可以实现继承。
但这种继承没有那么完美,Student继承了Professor、Teacher的所有属性,有些是Student不需要的,如果新建实例对象占用内存也大
Professor.prototype = {name: 'Mr. Zhang',tSkill: 'JAVA'}function Professor() {}var professor = new Professor();Teacher.prototype = professor;function Teacher() {this.name = 'Mr. Wang';this.mSkill = 'JS/JQ';}var teacher = new Teacher();Student.prototype = teacher;function Student() {this.name = 'Mr. Li';this.pSkill = 'HTML/CSS';}var student = new Student();console.log(student);
原型继承特点
1.Target.prototype = Origin.prototype 只会继承 Origin 构造函数原型上的属性和方法。
2.不会继承 Orgin 构造函数自身的属性和方法。
3.在 Target.prototype 上面新增属性和方法,Origin.prototype 也会同步更改(指向同一对象)。
//公共原型function Teacher() {this.name = 'Mr. Li';this.tSkill = 'JAVA';}Teacher.prototype = {pSkill: 'JS/JQ'}var t = new Teacher();console.log(t);function Student() {this.name = 'Mr. Wang';}Student.prototype = Teacher.prototype;Student.prototype.age = 18;var s = new Student();console.log(s);
二、call_apply
通过 call、apply 借用其它构造函数的属性和方法,但无法继承该构造函数原型上的属性和方法
这不是继承这是借用,Studnet借用Teacher中的函数与方法
Teacher.prototype.wife = 'Ms. Liu';function Teacher(name, mSkill) {this.name = name;this.mSkill = mSkill;}function Student(name, mSkill, age, major) {Teacher.apply(this, [name, mSkill]);//通过改变this的指向,返回Student的this,而不是Teacher中的thisthis.age = age;this.major = major;}var student = new Student('Mr. Zhang', 'JS/JQ', 18, 'Computer');console.log(student);
三、圣杯模式
还是不好,改变Teacher的原型就改变了Student的原型,改了Student就改了Teacher
因为它们俩的原型指向同一个空间,储存地址一样
function Teacher() {this.name = 'Mr. Li';this.tSkill = 'JAVA';}Teacher.prototype = {pSkill: 'JS/JQ'}var t = new Teacher();console.log(t);function Student() {this.name = 'Mr. Wang';}Student.prototype = Teacher.prototype;Student.prototype.age = 18;var s = new Student();console.log(s);

1.创建 Buffer 构造函数。
2.Buffer 构造函数继承 Origin 构造函数。
3.Target 构造函数继承 Buffer 构造函数实例化后的对象。
4.此时 Target 构造函数原型和 Origin 构造函数原型就不再指向同一对象。
5.实例化后的 target 对象继承了 Origin 构造函数原型上的属性和方法。
利用Buffer的实例对象,实例对象是新的空间
Student实例对象->Student.prototype(Buffer实例对象)->Buffer.prototype(Teacher.prototype)->Object.prototype
function Teacher() {this.name = 'Mr. Li';this.tSkill = 'JAVA';}Teacher.prototype = {pSkill: 'JS/JQ'}var t = new Teacher();console.log(t);function Student() {this.name = 'Mr. Wang';}function Buffer() {}Buffer.prototype = Teacher.prototype;var buffer = new Buffer();Student.prototype = buffer;//Student.prototype = new Buffer();//也行Student.prototype.age = 18;var s = new Student();console.log(s);

封装原型继承
function inherit(Target, Origin) {function Buffer() {}Buffer.prototype = Origin.prototype;Target.prototype = new Buffer();Target.prototype.constructor = Target;Target.prototype.super_class = Origin;}function Teacher() {}function Student() {}inherit(Student, Teacher);var s = new Student();var t= new Teacher();console.log(s);console.log(t);
function inherit(Target, Origin) {function Buffer() { }Buffer.prototype = Origin.prototype;Target.prototype = new Buffer();Target.prototype.constructor = Target;Target.prototype.super_class = Origin;}// function Teacher() { }// function Student() { }function Teacher() {this.name = 'Mr. Li';this.tSkill = 'JAVA';}function Student() {this.name = 'Mr. Wang';}inherit(Student, Teacher);var s = new Student();var t = new Teacher();console.log(s);console.log(t);
IIFE实现封装继承方法
Buffer形成闭包,但Buffer虽然没有重置,但这里面不受影响
var inherit = (function () {var Buffer = function () { }return function (Target, Origin) {Buffer.prototype = Origin.prototype;Target.prototype = new Buffer();Target.prototype.constructor = Target;Target.prototype.super_class = Origin;}})();Teacher.prototype.name = 'Mr. Zhang';function Teacher() { }function Student() { }inherit(Student, Teacher);Student.prototype.age = 18;var s = new Student();var t = new Teacher();console.log(s);console.log(t);
四、模块化
1.防止全局污染。
2.利于后期维护。
3.二次开发。
返回构造函数在外部使用,Programmer不返回
var inherit = (function () {var Buffer = function () { }return function (Target, Origin) {Buffer.prototype = Origin.prototype;Target.prototype = new Buffer();Target.prototype.constructor = Target;Target.prototype.super_class = Origin;}})();var initProgrammer = (function () {var Programmer = function () {}Programmer.prototype = {name: '程序员',tool: '计算机',work: '编写应用程序',duration: '10个小时',say: function () {console.log('我是一名' + this.myName + this.name + ', 我的工作是用' + this.tool + this.work + ', 我每天工作' + this.duration + ',我的工作需要用到' + this.lang.toString() + '。');}}function FrontEnd() {}function BackEnd() {}inherit(FrontEnd, Programmer);inherit(BackEnd, Programmer);FrontEnd.prototype.lang = ['HTML', 'CSS', 'JavaScript'];FrontEnd.prototype.myName = '前端';BackEnd.prototype.lang = ['Node', 'Java', 'SQL'];BackEnd.prototype.myName = '后端';return {FrontEnd: FrontEnd,BackEnd: BackEnd}})();var frontEnd = new initProgrammer.FrontEnd();var backEnd = new initProgrammer.BackEnd();frontEnd.say();backEnd.say();
总结

var func1 = (function () {var a = 1;console.log('a',a)return function () {a = 2console.log('a',a)}})();console.log(window)
func1未使用,但里面的方法运行了,打印window有,func1是返回的函数

打印
说明函数运行了
var func1 = (function () {var a = 1;console.log('a', a)// return function () {// a = 2// console.log('a', a)// }})();console.log(window)
五、作业
使用模块化开发实现以下功能:
1.打印一个参数值以内能被3或5或7整除的数。
2.打印斐波那契数列的第N位。
3.打印从0到一个数的累加值。
window.onload = function () {console.log(initFib(10));console.log(initDiv(100));console.log(initSum(100));}var initFib = (function () {function fib(n) {if (n <= 0) {return 0;}if (n <= 2) {return 1;}return fib(n - 1) + fib(n - 2);}return fib;})();var initDiv = (function () {function div(n) {var arr = [];for (var i = 0; i <= n; i++) {if (i % 3 === 0 || i % 5 === 0 || i % 7 === 0) {arr.push(i);}}return arr;}return div;})();var initSum = (function () {function sum(n) {var sum = 0;for (var i = 0; i <= n; i++) {sum += i;}return sum;}return sum;})();
