读书笔记-JavaScript面向对象编程(三)

第7章 浏览器环境

7.1 在HTML页面中引入JavaScript代码

7.2概述BOM与DOM(页面以外事物对象和当前页面对象)

7.3 BOM

  7.3.1 window对象再探(所以JavaScript核心函数也都是window对象的方法)

  7.3.2 window.navigator(浏览器信息,如window.navigator.userAgent)

  7.3.3 Firebug的备忘功能

  7.3.4 window.location(当前页面的URL信息,如设置href属性可实现页面跳转)

  7.3.5 window.history(访问页面的历史记录信息,三个方法:forward、back、go)

  7.3.6 window.frames(当前页面中所有frame的集合)

  7.3.7 window.screen(浏览器以外的桌面信息)

  7.3.8 window.open()/close()(打开/关闭新窗口,现已被页面内自定义弹窗代替)

  7.3.9 window.moveTo()/resizeTo()(移动浏览器窗口位置/调整浏览器窗口大小,不建议使用)

  7.3.10 window.alert()/prompt()/confirm()(系统弹窗)

  7.3.11 window.setTimeout()/setInterval()(系统定时器,延时/循环)

setTimeout("alert('boo')",2000);//首参数是一个可以被eval执行的字符串,但应尽量避免
setTimeout(function(){alert('boo')},2000)//推荐:将相关函数调用封装在另一个函数中

  7.3.12 window.document(等同于DOM)

7.4 DOM

  7.4.1 Core DOM与HTML DOM(XML与HTML)

  7.4.2 DOM节点的访问(nodeType、nodeName、nodeValue、documentElement(根节点)、childNodes(子节点集合)、parentNode(父节点)、attributes(节点的属性集合)、textContent(获取节点中的文本内容)、innerHTML)

  (getElementByTagName、getElementByName,getElementById、nextSibling、previousSibling、firstChild、lastChild)

  7.4.3 DOM节点的修改(属性赋值或innerHTML覆盖)

  7.4.4 新建节点(creatElement、creatTextNode并appendChild,或使用innerHTML、choneNode(true/false)、insertBefore)

  7.4.5 移除节点(removeChild,replaceChild,innerHTML设置为‘’)

  7.4.6 只适用于HTML的DOM对象(document.body等价于document.getElementByTagName('body')[0])

  (document.images/applets/links/anchors/forms,document.write,document.cookies/title/referrer/domain)

7.5 事件

  7.5.1 内联HTML属性法

<div onclick="alert('boo!')">click</div>

  7.5.2 元素属性法

<div id="mybtn">click</div>
//以下JS部分
document.getElementById('mybtn').onclick=function(){alert('boo!')}

  7.5.3 DOM的事件监听器(DOM level 2)

var btn=document.getElementById('mybtn');
btn.addEventListener('click',function(){alert('boo!')})

  7.5.4 捕捉法与冒泡法(addEventListener的第三个参数为false只使用冒泡法,stopPropagation阻止冒泡 )

  7.5.5 阻断传播(removeEventListener移除事件,由匿名函数定义的监听器是不能被移除的)

  7.5.6 防止默认行为(preventDefault)

  7.5.7 跨浏览器事件监听器(IE中没有addEventListener用attachEvent,没有target用srcElement,没有stopPropagetion用cancelBubble为true,没有preventDefault用returnValue为false,没有removeEventListener用detachEvent)

  7.5.8 事件类型

7.6 XMLHttpRequest对象

  7.6.1 发送请求

var xhr=new XMLHttpRequest();
xhr.onreadystatechange=myCallback;
xhr.open('GET','somfile.txt',true);
xhr.send('')

   7.6.2 处理响应(当readystate为4时响应返回,继续检测xhr.status服务器返回代码,并进行下一步处理)

  7.6.3 在早于7的IE版本中创建XMLHttpRequest对象 

var xhr=new ActiveXObject('MSXML2.XMLHTTP.3.0');

  7.6.4 A代表异步

  7.6.5 X代表XML

  7.6.6 实例示范

7.7 本章小结

7.8 练习题

第8章 编程模式与设计模式

8.1 编程模式

  8.1.1 行为隔离(HTML、CSS与JS隔离,即内容、外观与行为隔离)

  8.1.2 命名空间(只定义一个全局变量,其他变量和方法定义为该变量的属性,很多库都实现的namespace方法如下)

var MYAPP={}
MYAPP.namespace=function(str){
  var parts=str.split('.'),curr=MYAPP;
  for(var i in parts){
    if(!curr[parts[i]]){curr[parts[i]]={}}
    curr=curr[parts[i]]
  }
}
MYAPP.namespace('dom.style');
//等价于如下
var MYAPP={
  dom:{
    style:{}
  }  
}

  8.1.3 初始化分支(根据浏览器特性,一开始判断后再给特定功能函数赋值,当这些功能函数被调用,就用不需要再做探测了,兼容性初始化)

var MYAPP={};
MYAPP.event={
  addListener:null,
  removeListener:null
}
if(typeof window.addEventListener==='function'){
  MYAPP.event.addListener=function(el,type,fn){el.addEventListener(type,fn,false);}
  MYAPP.event.removeListener=function(el,type,fn){el.removeEventListener(type,fn,false);}
}else if(typeof document.attachEvent==='function'){//IE
  MYAPP.event.addListener=function(el,type,fn){el.attachEvent('on'+type,fn);}
  MYAPP.event.removeListener=function(el,type,fn){el.detachEvent('on'+type,fn);}
}else{//older browsers
  MYAPP.event.addListener=function(el,type,fn){el['on'+type]=fn;}
  MYAPP.event.removeListener=function(el,type,fn){el['on'+type]=null;}
}

  8.1.4 延迟定义(同初始化分支。第一次调用时被定义)

var MYAPP={};
MYAPP.myevent={
  addListener:function(el,type,fn){
    if(typeof window.addEventListener==='function'){
      MYAPP.myevent.addListener=function(el,type,fn){el.addEventListener(type,fn,false);}
    }else if(typeof document.attachEvent==='function'){//IE
      MYAPP.myevent.addListener=function(el,type,fn){el.attachEvent('on'+type,fn);}
    }else{//older browsers
      MYAPP.myevent.addListener=function(el,type,fn){el['on'+type]=fn;}
    }
    MAAPP.myevent.addListener(el,type,fn);
  }
}

  8.1.5 配置对象(用于有很多参数的函数,用对象替代参数可以不考虑参数顺序,跳过默认值,扩展性更强,可读性更好)

  8.1.6 私有属性和方法(对象方法内部定义的局部变量和函数)

  8.1.7 特权函数(建立公共函数,它们可以访问内部私有属性和方法,如get/set方法)

  8.1.8 私有函数的公有化

var MYAPP={};
MYAPP.dom=(function(){
  var _setStyle=function(el,prop,value){console.log('setstyle')}
  var _getStyle=function(el,prop){console.log('getstyle')}
  return {
    setstyle:_setStyle,
    getstyle:_getStyle,
    yetAnother:_setStyle
  }
})()
MYAPP.dom.setstyle=function(){alert('b')}//外部可以改写setstyle方法,yetAnother依然指向_setStyle

  8.1.9 自执行函数(保证命名空间,特别适合执行一次性初始化任务)

  8.1.10 链式调用(前一个方法的结果(即返回对象)来调用下一个方法)

  8.1.11 JSON

8.2 设计模式

  8.2.1 单件模式1

var single={};//最基本的单件模式

  8.2.2 单件模式2(仅生成一个对象)

function Logger(){
  if(typeof global_log==='undefined'){global_log=this;}
  return global_log;
}
var a=new Logger();
var b=new Logger();
alert(a===b);//true,此方法产生全局变量global_log
var Logger=(function(){
  var instance=null;
  return {
    getinstance:function(){
      if(instance==null){instance=this};
      return instance;
    }
  }
})()
var a=Logger.getinstance();
var b=Logger.getinstance();
alert(a===b);//true,利用只执行函数和闭包来实现

   8.2.3 工厂模式(创建对象模式)

//假如我有三个不同的构造器,它们功能相似,但处理细节不同
var MYAPP={};
MYAPP.dom={};
MYAPP.dom.Text=function(){
  this.insert=function(where){
    var txt=document.createTextNode(this.url);
    where.appendChild(txt)
  }
};
MYAPP.dom.Link=function(){
  this.insert=function(where){
    var link=document.createElement('a');
    link.href=this.url;
    link.appendChild(document.createTextNode(this.url));
    where.appendChild(link)
  }
};
MYAPP.dom.Image=function(){
  this.insert=function(where){
    var img=document.createElement('img');
    img.src=this.url;
    where.appendChild(img)
  }
};
//使用三个构造器的方法都一样,设置URL属性并调用insert方法
var t=new MYAPP.dom.Text();
t.url='http://www.baidu.com/1.jpg';
t.insert(document.body)
//如果我们暂时不知道创建哪种对象,需要根据用户触发按钮来决定,按钮提供type表示创建类型,如下
var o;
if(type ==='Text'){o=new MYAPP.dom.Text();
}else if(type ==='Link'){o=new MYAPP.dom.Link();
}else if(type ==='Image'){o=new MYAPP.dom.Image();}
o.url='http://...';
o.insert();
//添加工厂方法factory,避免如上判断
MYAPP.dom.factory=function(type){return new MYAPP.dom[type];}
var o=MYAPP.dom.factory(type);
o.url='http://...';
o.insert();

  8.2.4 装饰者模式(结构性模式,主要拓展对象的功能)

//装饰者模式实例:装饰一颗圣诞树
var tree={
  decorate:function(){console.log('确保树不会倒');}
};
//接着定义方法用于添加额外的装饰器,装饰器实现为构造器函数,都继承tree
tree.getDecorate=function(deco){tree[deco].prototype=this;return new tree[deco];}//让每一个装饰后对象的原型等于父级
//下面创建装饰器,将他们设置为tree的属性(保证命名空间),它们提供decorate方法,单先调用父类的decorate
tree.RedBalls=function(){
  this.decorate=function(){this.RedBalls.prototype.decorate();console.log('上面放一些红球')}
}
tree.BlueBalls=function(){
  this.decorate=function(){this.BlueBalls.prototype.decorate();console.log('下面放一些蓝球')}
}
tree.Angel=function(){
  this.decorate=function(){this.Angel.prototype.decorate();console.log('在树顶放一个小天使')}
}
//再把所有的装饰器都添加到基础对象上
tree=tree.getDecorate('BlueBalls')
tree=tree.getDecorate('Angel')
tree=tree.getDecorate('RedBalls')
tree.decorate();
//tree.Redballs的原型为父类tree.Angel的原型为父类tree.RedBalls的原型为父类tree(初始状态)
console.log(tree.getDecorate('BlueBalls').getDecorate('Angel').getDecorate('RedBalls'))

  8.2.5 观察者模式(行为模式,主要用于处理不同对象间的交互通信)

//先创建一个观察者,它包含由回调函数构成的订阅者数组,用于增加和删除订阅者的方法,publish授受并传递数据给订阅者,make将任意对象转变为发行商并添加上述方法
var observer={
  addSubscriber:function(callback){this.subscribers[this.subscribers.length]=callback;},
  removeSubscriber:function(callback){
    for(var i=0; i<this.subscribers.length;i++){if(this.subscribers[i]==callback){delete(this.subscribers[i])}}
  },
  publish:function(what){
    for(var i=0; i<this.subscribers.length;i++){if(typeof this.subscribers[i]==='function'){this.subscribers[i](what)}}
  },
  make:function(o){
    for(var i in this){o[i]=this[i];o.subscribers=[]}
  }
}
//接下来我们创建一些订阅者,它们可以是任意对象,唯一职责就是在发生重要事件时调用publish方法
var blogger={
  writeBlogPost:function(){var content='今天是'+new Date();this.publish(content);}
}
var latimes={
  newIssue:function(){var paper='火星人来地球了!';this.publish(paper);}
}
//它们都很容易转变为发行商
observer.make(blogger);
observer.make(latimes);
//于此同时,准备两个简单对象
var jack={
  read:function(what){console.log('我刚看了'+what)}
}
var jill={
  gossip:function(what){console.log('你没听到我的话,但'+what)}
}
//将他们订阅blogger,只需要提供事件发生时的回调函数
blogger.addSubscriber(jack.read);
blogger.addSubscriber(jill.gossip);
//当blogger写了新的博客时,jack和jill都会收到通知
blogger.writeBlogPost();
//任何时候jill都可以取消订阅,再推送时将不再收到通知
blogger.removeSubscriber(jill.gossip);
blogger.writeBlogPost();
//jilly也可以订阅latimes,因为一个订阅者可以对应多个发行商
latimes.addSubscriber(jill.gossip);
latimes.newIssue()

--完--

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏DOTNET

【翻译】MongoDB指南/引言

【原文地址】https://docs.mongodb.com/manual/ 引言 MongoDB是一种开源文档型数据库,它具有高性能,高可用性,自动扩展性 1...

2096
来自专栏python爬虫日记

转载:python的编码处理(一)

最近业务中需要用 Python 写一些脚本。尽管脚本的交互只是命令行 + 日志输出,但是为了让界面友好些,我还是决定用中文输出日志信息。 

642
来自专栏禁心尽力

数据库设计之数据库,数据表和字段等的命名总结

数据库命名规则: 根据项目的实际意思来命名。 数据表命名规则: 1.数据表的命名大部分都是以名词的复数形式并且都为小写; 2.尽量使用前缀"table_"; 3...

1865
来自专栏计算机视觉与深度学习基础

Leetcode 211 Add and Search Word - Data structure design

Design a data structure that supports the following two operations: void addWor...

1815
来自专栏PHP技术

给PHP开发者讲讲PHP源码-第二部分

欢迎来到"给PHP开发者的PHP源码"系列的第二部分。 在上一篇中,ircmaxell说明了你可以在哪里找到PHP的源码,它的基本目录结构以及简单地介绍了一些C...

3428
来自专栏york技术分享

awk 使用教程 - 通读篇(30分钟入门)

很多刚接触awk,sed等命令时,看到帮助文档一堆参数,一堆符号感觉有点慌,我刚开始学习时也出现过这样的问题,这篇文章从我们工作遇到的问题出发,由浅入深,重点在...

56717
来自专栏IT可乐

Redis详解(四)------ redis的底层数据结构

  上一篇博客我们介绍了 redis的五大数据类型详细用法,但是在 Redis 中,这几种数据类型底层是由什么数据结构构造的呢?本篇博客我们就来详细介绍Redi...

780
来自专栏MasiMaro 的技术博文

PE文件详解(七)

本文转载自小甲鱼PE文件讲解系列原文传送门 这次主要说明导出表,导出表一般记录着文件中函数的地址等相关信息,供其他程序调用,常见的.exe文件中一般不存在导...

931
来自专栏黑白安全

switch语句

多级elseif 显然是用于那些可能需要进行多级判断的情况。如果$a,正好是大于10,只需判断一次,但如果$a小于10那就必须经过“是不是大于10?,是不是等于...

573
来自专栏java学习

Java每日一练(2017/9/14)

最新通知 ●回复"每日一练"获取以前的题目! ●【新】Android视频更新了!(回复【安卓视频】获取下载链接) ●【新】Ajax知识点视频更新了!(回复【学习...

25612

扫码关注云+社区