13.1原型链继承
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();
console.log(teacher);
Professor.prototype = {
name: 'Mr.Zhang',
tSkill: 'JAVA'
}
function Professor(){}
var professor = new Professor();
// ---------------------------------
Teacher.prototype = professor;
function Teacher(){
this.name = 'Joe';
this.mSkill = 'JS/JQ';
}
var teacher = new Teacher();
console.log(teacher);
//------------------------------
Student.prototype = teacher;
function Student(){
this.name = 'Lily';
this.pSkill = 'HTML/CSS';
}
var student = new Student(); // student继承了上面所有原型的属性
console.log(student);
13.2 call , apply
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]); // 借用 Teacher 的属性
this.age = age;
this.major = major;
}
var student = new Student('Tom', 'JS/JQ', 18, 'Computer');
console.log(student);//无Teacher.prototype.wife
13.3圣杯模式
问题
// 公共原型
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; // 继承Teacher的原型
Student.prototype.age = 18;
// 这里更改Student的prototype,Teacher 的 prototype 也会被修改
var s = new Student();
console.log(s);
修改:圣杯模式
function Teacher(){
this.name = 'Mr. Li';
this.tSkill = 'JAVA';
}
Teacher.prototype = {
pSkill: 'JS/JQ',
obj: {a: 1}
}
var t = new Teacher();
console.log(t);
function Student(){
this.name = 'Mr. Wang'
}
// 缓冲构造函数
function Buffer(){}
Buffer.prototype = Teacher.prototype;
var buffer = new Buffer();
console.log(buffer);
Student.prototype = buffer;
// 相当于继承 Buffer 的原型,继承过来的东西不能修改
Student.prototype.obj.a = 4;
// 问题:修改引用值可以修改成功,为什么❓
Student.prototype.age = 18;
// 这时候修改Student的prototype 和Teacher的prototype没有关系了
var s = new Student();
console.log(s);
封装
function Teacher(){}
function Student(){}
function Buffer(){}
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(); // new 一定要放在 prototype 赋值的下方
Target.prototype.constructor = Target; // 还原构造器
Target.prototype.super_class = Origin; // 继承源
}
13.4CSS 圣杯模式 双飞翼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* 清除浮动 */
.clearfix::after{
content: '';
display: table;
clear: both;
}
.wrap {
width: 700px;
margin: 0 auto;
border: 1px solid #000;
}
.top,
.foot {
height: 50px;
background-color: #000;
}
.main {
padding: 0 100px;
overflow: hidden;
}
.main .left,
.main .content,
.main .right {
float: left;
position: relative;
background-color: green;
/* 圣杯模式主要逻辑是赋值 */
margin-bottom: -2000px;
padding-bottom: 2000px;
}
.main .left {
left: -100px;
width: 100px;
}
.main .content {
width: 100%;
margin-left: -100px;
background-color: red;
}
.main .right {
left: 100px;
width: 100px;
margin-left: -100px;
}
</style>
</head>
<body>
<div class="wrap">
<div class="top"></div>
<div class="main clearfix">
<div class="left">123</div>
<div class="content">234
234</div>
<div class="right">123</div>
</div>
<div class="foot"></div>
</div>
<script type="text/javascript"></script>
</body>
</html>
13.5闭包
function test(){
var num = 0; // 私有变量
function add(){
num++;
console.log(num);
}
return add;
}
var add = test();
add();
add();
add();
以闭包的方式包装圣杯模式
1.防止对全局环境的污染
2.利于后期的开发
// 企业级写法 模块化开发
var inherit = (function test(){
var Buffer = function(){}; // 有自己的命名空间了
return function(Target, Origin){
Buffer.prototype = Origin.prototype;
Target.prototype = new Buffer(); // new 一定要放在 prototype 赋值的下方
Target.prototype.constructor = Target; // 还原构造器
Target.prototype.super_class = Origin; // 继承源
}
})();
Teacher.prototype.name = 'Mr Zhang';
function Teacher(){}
function Student(){}
function Buffer(){}
inherit(Student, Teacher);
Student.prototype.age = 18
var s = new Student();
var t = new Teacher();
console.log(s);
console.log(t);
13.6应用
写自启动函数, 是因为加载的时候就需要启动,把里面的函数return 给变量initProgrammer保存 让initProgrammer 接收, 是因为不想里面抛出来的函数立即执行,让它等待着,等需要执行的时候再执行
var inherit = (function test(){
var Buffer = function(){}; // 有自己的命名空间了
return function(Target, Origin){
Buffer.prototype = Origin.prototype;
Target.prototype = new Buffer(); // new 一定要放在 prototype 赋值的下方
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();
企业协同开发
window.onload = function(){
init();
}
function init(){
initCompute();
initFunctions();
}
// 按需启动功能
var initCompute = (function(){
var a = 1,
b = 2;
function add(){
console.log(a + b);
}
function minus(){
console.log(a - b);
}
function mul(){
console.log(a * b);
}
function div(){
console.log(a / b);
}
return function(){
add();
minus();
mul();
div()
}
})();
var initFunctions = (function(){
})();
// 或者用插件化开发
;(function(){
var Slider = function(opt){}
Slider.prototype = {
}
window.Slider = Slider;
})();
var slider = new Slider({
});
整合下面3个功能(模块化开发:独立的作用域空间,将抛出来的函数保存到GO)
打印100以内的能被 3 或 5 或7 整除的数
打印斐波那切数列的第n位
打印从0到一个数的累加值
window.load(){
init();
}
function init(){
console.log(initFb(10));
console.log(initDiv(100));
}
var initFb = (function(){
function fb(n){
if(n <= 0){
return 0;
}
if(n <= 2){
return 1;
}
return fb(n - 1) + fb(n - 2);
}
return fb;
})();
var initBiv = (function(){
function div(n){
for(var i = 0;i <= n; i++){
if(i % 3 === 0 || i % 5 === 0 || i % 7 === 0 ){
arr.push(i);
}
}
return arr;
}
return div;
})();