JS面向对象

   

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

第一课时 入门基础

知识点:

  • 操作系统就是个应用程序
  • 只要是应用程序都要占用物理内存
  • 浏览器本身也是一个应用程序
  • 浏览器本身只懂得解析 HTML
  • 调用浏览器这个应用程序的一个功能绘制

1、javascript介绍

  • JavaScript 操作 DOM 的本质是=获取+触发+改变

  • 目的:就是用来操作内存中的 DOM 节点

    • 修改 DOM 节点的属性
    • 过 javascript 语法组织逻辑代码操作DOM
    • BOM(window) 它包含了 DOM
    • DOM(document)
    • script 脚本推荐放在最下边好处:防止因网络问题,页面加载时间长,出现空白;即便网络问题,浏览器也把 DOM 加载渲染完成,等待从服务端下载完 js 脚本,出现效果
    • css 不放在最下面原因通俗地讲:好比先穿好衣服在出去,浏览器先把 css样式准备好,在加载结构层,使得页面有样子;如果放在下面,因为页面是从上往下加载,没有 css ,就剩下裸露的标签,很难看,使得用户体验不好

2、基于对象的内存管理

  • javascript 就是来操作这些对象
    • 通过逻辑组织对象之间的关系和行为
    • 如何操作这些对象?通过变量引用

3、变量

  • 变量本质是一个空盒子,里面记录了一个内存地址,使能找到内存中的对象,保存了指向具体的实在的东西的地址
  • 变量存在栈中,对象存在堆中
  • 变量的意义:方便我们去操作对象
  • 变量的几种引用方式
    • 指针( C 语言中叫法)
    • 引用( Java )
    • 变量
  • 例如:
    • var b = document.body 含义:把 body 这个对象在内存中的地址放到b变量里面,变量 b ( b 是内存地址的别名)本身也存在内存中,以后的操作是针对 body 这个地址
  • 变量命名规范
    • 由字母( a-zA-Z )数字( 0-9 )下划线( _ )以及美元符号( $ )
    • 不能由数字开头
    • 命名尽量用英文并且具有一定的含义
    • 如果有多个英文单词,后面单词的首字母大写
    • 不能使用关键字
    • 首字母不要大写,大写是有特殊含义的

DOM在内存中的一些图示

面向对象总结 随笔 第1张

面向对象总结 随笔 第2张

面向对象总结 随笔 第3张

面向对象总结 随笔 第4张

第二课时

回顾上节:

  • 1、 javascript 介绍

  • 2、基于对象的内存管理

  • javascript 就是来操作这些对象

    • 通过逻辑组织对象之间的关系和行为
    • 如何操作这些对象?通过变量引用
  • 3、变量

知识点:

1、 window 作用域

  • 只要在 script 标签中定义的变量,默认就在 window 的作用域之下
  • 默认就是 window 这个对象里面写代码

2、数据类型

如何判断js中的数据类型:

  • typeof 、 instanceof 、 constructor 、 prototype 方法比较

  • 如何判断 js 中的类型呢,先举几个例子:

vara ="iamstring."; varb =222; varc= [1,2,3]; vard =newDate(); vare =function(){alert(111);}; varf =function(){this.name="22";}; 

最常见的判断方法 : typeof

alert(typeofa) ------------> string
alert(typeofb) ------------> number
alert(typeofc) ------------> object
alert(typeofd) ------------> object
alert(typeofe) ------------>function
alert(typeof f) ------------>function
  • 其中 typeof 返回的类型都是字符串形式,需注意,例如:
alert(typeofa =="string") ------------->true
alert(typeofa ==String) --------------->false
  • 另外 typeof 可以判断 function 的类型;在判断除 Object 类型的对象时比较方便。

判断已知对象类型的方法 : instanceof

alert(c instanceofArray) --------------->true
alert(d instanceofDate)
alert(f instanceofFunction) ------------>true
alert(f instanceoffunction) ------------>false
  • 注意 : instanceof 后面一定要是对象类型,并且大小写不能错,该方法适合一些条件选择或分支。

根据对象的 constructor 判断 : constructor

alert(c.constructor === Array) ---------->true
alert(d.constructor === Date) ----------->true
alert(e.constructor === Function) ------->true
  • 注意: constructor 在类继承时会出错

  • 例子:

functionA(){};
functionB(){};
A.prototype = newB();//A继承自B
varaObj =newA();
alert(aobj.constructor === B) -----------> true; alert(aobj.constructor === A) -----------> false; 
  • 而 instanceof 方法不会出现该问题,对象直接继承和间接继承的都会报 true :
alert(aobj instanceofB) ---------------->true;
alert(aobj instanceofB) ---------------->true;
  • 言归正传,解决 construtor 的问题通常是让对象的 constructor 手动指向自己:
aobj.constructor = A; //将自己的类赋值给对象的constructor属性 alert(aobj.constructor === A) -----------> true; alert(aobj.constructor === B) -----------> false;//基类不会报true了; 

通用但很繁琐的方法 : prototype

alert(Object.prototype.toString.call(a) === ‘[objectString]’) ------->true; alert(Object.prototype.toString.call(b) === ‘[objectNumber]’) ------->true; alert(Object.prototype.toString.call(c) === ‘[objectArray]’) ------->true; alert(Object.prototype.toString.call(d) === ‘[objectDate]’) ------->true; alert(Object.prototype.toString.call(e) === ‘[objectFunction]’) ------->true; alert(Object.prototype.toString.call(f) === ‘[objectFunction]’) ------->true; 
  • 大小写不能写错,比较麻烦,但胜在通用。
  • 通常情况下用 typeof 判断就可以了,遇到预知 Object 类型的情况可以选用 instanceof 或 constructor 方法

Javascript的数据类型有六种(ES6新增了第七种 Symbol )

  • 数值( number ):整数和小数(比如1和3.14)
  • 字符串( string ):字符组成的文本(比如”Hello World”)
  • 布尔值( boolean ):true(真)和false(假)两个特定值
  • undefined :表示 未定义 或不存在,即此处目前没有任何值
  • null :表示空缺,即此处应该有一个值,但目前为空
  • 对象( object ):各种值组成的集合
  • 通常,我们将数值、字符串、布尔值称为原始类型( primitive type )的值,即它们是最基本的数据类型,不能再细分了。而将对象称为合成类型( complex type )的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。至于 undefined 和 null ,一般将它们看成两个特殊值

内存中一共分为几种对象:

  • 变量
  • DOM 对象
  • 常量
  • 自定义对象

数据类型转换

转换函数

  • toString() 转换为字符串,在JavaScript中所有数据类型都可以转换为 string类型
varn1 =12;
varn2 =true; vara = [1,2,3]; varo = {}; functionf(){} n1.toString(); //"12" n2.toString(); //"true" a.toString(); //"1,2,3" o.toString(); //"[object Object]" f.toString(); //"function f(){}" 
  • parseInt() 解析出一个 string 或者 number 类型的整数部分,如果没有可以转换的部分,则返回 NaN ( not a number )

    varn1 ="12";
    varn2 ="23hello"; varn3 ="hello"; parseInt(n1);//12 parseInt(n2);//23 parseInt(n3);//NaN 
    • parseFloat() 解析出一个 string 的浮点数部分,如果没有可以转换的部分,则返回 NaN ( not a number )
    varn1 ="1.2.3";
    varn2 ="1.2hello" varn3 ="hello" parseFloat(n1);//1.2 parseFloat(n2);//1.2 parseFloat(n3);//NaN 

强制类型转换

  • Boolean(value) - 把给定的值转换成 Boolean 型
Boolean(123);//true Boolean("");//false Boolean([]);//true Boolean({});//true Boolean(null);//false Boolean(undefined);//false 
  • Number(value) -把给定的值转换成数字(可以是整数或浮点数)
Number("123");//123 Number("123h");//NaN Number(true);//1 Number(false);//0 Number(undefined);//NaN Number(null);//0 Number([]);//0 Number({});//NaN 
  • String(value) - 把给定的值转换成字符串

    String(123);//"123" String([1,2]);//"1,2" String(undefined)//"undefined" String(null)//"null" String({})//"[object Object]" 

隐式转换

  • 数字+字符串:数字转换为字符串 console.log(12+"12") ; //1212
  • 数字+布尔值: true 转换为 1 , false 转换为 0 console.log(12+true) ; //13
  • 字符串+布尔值:布尔值转换为true或false console.log("hello"+true) ; // hellotrue
  • 布尔值+布尔值 console.log(true+true) ; //2

null和undefined

  • undefined 表示一种未知状态,声明了但没有初始化的变量,变量的值时一个未知状态。访问不存在的属性或对象 window.xxx )方法没有明确返回值时,返回值是一个 undefined. 当对未声明的变量应用 typeof 运算符时,显示为 undefined 。
  • null 表示尚未存在的对象, null 是一个有特殊意义的值。可以为变量赋值为 null ,此时变量的值为“已知状态”(不是 undefined ),即 null 。(用来初始化变量,清除变量内容,释放内存)
undefined==null//结果为true,但含义不同。 undefined===null//false,两者类型不一致,前者为“undefined”,后者为“object” 

3、javascript脚本执行顺序

  • 第一步定义: 分为 var 定义 和函数定义 function
  • 第二步执行: 其他所有
  • 先从上往下定义完所有的后,再从上往下执行 除了 var function 定义外的 其他都是执行 如:赋值 函数调用
  • 在栈里面找到的,就不去堆里面找,因为栈空间小,就近原则【总之:先在栈里面找,找不到再去堆里面找】在栈里面开辟,就能找到堆里面的地址 如: var b = function(){}

总结一下 == 运算的规则:(隐式转换)

  • JS 中的值有两种类型:原始类型( Primitive )、对象类型( Object )。

  • 原始类型包括: Undefined 、 Null 、 Boolean 、 Number 和 String 等五种。

  • Undefined 类型和 Null 类型的都只有一个值,即 undefined 和 null ; Boolean 类型有两个值: true 和 false ; Number 类型的值有很多很多; String 类型的值理论上有无数个。

  • 所有对象都有 valueOf() 和 toString() 方法,它们继承自 Object ,当然也可能被子类重写

  • undefined == null ,结果是 true 。且它俩与所有其他值比较的结果都是 false 。

  • String == Boolean ,需要两个操作数同时转为 Number 。

  • String/Boolean == Number ,需要 String/Boolean 转为 Number 。

  • Object == Primitive ,需要 Object 转为 Primitive (具体通过 valueOf 和 toString 方法)

第三课时

上节回顾:

  • 1、 window 作用域

    • 只要在 script 标签中定义的变量,默认就在 window 的作用域之下
    • 默认就是 window 这个对象里面写代码
  • 2、数据类型

    • number :数字
    • string :字符类型,必须用引号引起来
    • boolean :布尔类型 true false
    • null :变量引用了一块堆中一个空的空间
    • object :引用对象类型(存在于堆里面)
    • array :数组类型
    • function :函数数据类型
  • 对象数据类型: object , array , function

  • 3、 javascript 脚本执行顺序

    • 定义 var function
    • 执行 其他所有

知识点:

1、运算符

  • 算术运算符( + , - , * , / , % , ++ , -- )

    • 如果引用所指的地方是 null 的话,那么在运算中就会自动变成 0
    • % 运算符 如: 4%5 取模 模是 4 7%5 取模 模是 7-5=2
  • 字符串和数字相加的情况:

    • 左右都是数字:数字相加
    • 左右有一个字符串:字符串拼接
    • 左右边有一个 null : null 看做 0
    • 左右边有一个 undefined :结果是 NAN ( not is number )
  • 赋值运算符( = , -= , += , *= , /= , %= )

  • 比较运算符( == , === , != , > , < , >= , <= )

    • 先执行表达式计算再赋值
    • == 和 != 在比较之前首先让双方的值做隐士类型转换, === 不转换
  • 逻辑运算符( || , && , ! )

    • || 在js中和PHP中是不一样的 js中返回逻辑或的左边或右边的一个结果 PHP返回 || 或出来以后的结果即: true false
    • 特殊性(注意)—一定要记住(这个特性和其他编程语言不一样):在 js 里返回不是布尔值
    • || 短路运算 第一个条件为真 后面不执行
    • && 把表达式最后一个值返回(注意这里)

条件运符( 表达式1?表达式2:表达式3 )三元运算符

  • 表达式1?表达式2:表达式3 表达式1为真 返回表达式2 否则返回表达式3
  • 三元运算符 可以多层次嵌套使用

2、在js中 有四种被认为是  :

  • undefined
  • null
  • false
  • 0
  • 例子: var age = prompt("温馨提示:","请输入您的年龄")||0
  • 当点击取消的时候,如果出现 undefined null fasle 0 表示非的逻辑 那么 ||就会过滤,取右边的值 0

第四课时

上节回顾:

  • 1、运算符

    • 算术运算符( + , - , * , / , % , ++ , -- )
    • 如果 + 号左边和右边有一边是字符串类型的数据的话,这个时候就变成字符串拼接
    • var str = "你好"+123; //你好123
    • var count = 2;
    • var str1 = "你叫了我第"-count+"次"; //你叫了我第2次
    • 如果引用所指的地方是 null 的话,那么在运算中就会自动变成0
  • 2、赋值运算符 *( = , -= , += ,` , /= , %=`)

  • 3、 比较运算符( ==,===,!=,>,<,>=,<= )

    • 先执行表达式计算再赋值
    • == 和 != 在比较之前首先让双方的值做隐士类型转换, === 不转换
  • 4、逻辑运算符( ||,&&,! )
  • 5、条件运算符( 1>2?3:4 )

知识点:

1、 console.log 调试程序

  • 开发中大量使用这个 而不用 alert

2、条件结构

  • if

javascript 中 if 语句优化写法

  • 使用常见的三元操作符
if(foo) bar();elsebaz(); ==> foo?bar():baz(); if(!foo) bar();elsebaz(); ==> foo?baz():bar(); if(foo)returnbar();elsereturnbaz(); ==>returnfoo?bar():baz(); 
  • 使用 and(&&) 和 or(||) 运算符
if(foo) bar(); ==> foo&&bar();
if(!foo) bar(); ==> foo||bar(); 
  • if...else
  • if...else if...else
  • 当通过判断返回某个值的时候,优先使用三元表达式
  • 当通过判断执行 N 段逻辑代码的时候,只能用条件结构

第五课时

上节回顾:

  • 1、 console.log 调试程序
  • 2、条件结构 
    if 
    if...else 
    if...else if...else
    • 当通过判断返回某个值的时候,优先使用三元表达式
    • 当通过判断执行 N 段逻辑代码的时候,只能用条件结构

知识点:

1、 switch

  • switch case break default 条件 判断 退出 默认

    • a.只要匹配上一个 case ,那么它下面的所有的 case 都会执行包括 default
    • b. break 的意思跳出当前结构

2、 for

  • 循环有三个要素
    • a.循环变量
    • b.判断(循环体)
    • c.改变循环变量
    • d. continue 的意思结束本次循环进入下次循环
  • continue 结束本次循环,继续下一次循环 当前这次循环不做 直接做下面的
  • break 结束后面的循环不做了

第六课时

上节回顾:

1、 switch

  • switch case break default 条件 判断 退出 默认
    • a.只要匹配上一个 case ,那么它下面的所有的 case 都会执行包括 default
    • b. break 的意思跳出当前结构

2、 for

  • 循环有三个要素
    • a.循环变量
    • b.判断条件(循环体)
    • c.改变循环变量
    • d. continue 的意思结束本次循环进入下次循环

知识点:

1、 while/do...while 没有谁好谁坏 只有适应场景不同

  • 比如:先吃饭 在买单 do..while 用户体验高 有风险 扫雷游戏也是先体验 在问是否退出 提高体验
  • 比如:先买单 在吃饭 while 用户体验不高
  • 一般情况下面,如果条件判断是 数字的 比较 ==<> , for 循环优先.
  • 如果是 非数值相关的 比较循环, while 优先

2、代码内存解析

闭包

  • a.程序永远是先定义后执行
  • b.执行永远从上到下
  • c.函数定义的话在堆(只是一个地址而已)
  • d.函数调用的时候,就会有自己的堆和栈( 闭包 )

闭包 作用域

  • 记住:先定义 var function 在从上往下执行
  • 定义定义在自己的栈里面 执行在自己的堆里面
  • 运行在运行的环境中
  • 函数每调用前 只是一个地址
  • 只要调用一次函数就会动态开辟一块内存 创建一个封闭的空间 在自己的封闭的空间的栈中定义 var 在执行
  • 函数执行完 里面的东西全部销毁
//alert(x);//9:执行弹出x,结果x没定义,错误.
alert(i);//9:执行弹出i,然而i之前已经定义,只不过没地址,因此是undefiend vari =10;//1:var i; 10:把常量池中10的地址赋给栈中的i varj ="你好";//2:var j; 11:把常量池中 你好 的地址复给栈中的j vark = z =null;//3:var k,z; 12:把堆中null的地址赋值给z和k varm =function(){//4:var m; 5:function匿名函数 13:把匿名函数在堆中的地址赋给栈中的m alert(2); } varb =document.body;//6:var b; 14:把堆中document.body对象的地址赋给栈中的b varf =true;//7:var f; 15:把常量池中true的地址赋给栈中的变量f functionm(){//8:function m; alert(1); } 
functionm(){
 c = 50;//在局部变量中找不到定义的c 沿着作用域链找到了全局变量的c alert('哈哈哈'); //var c; } varc =150;// 函数m()还未执行到 还没被销毁 此时全局c的值c=50 m(); varc =20;//到这里一步 m()已经执行完了 函数已经销毁了 这里的c还是20 alert(c);//20 
functionm(){
 c = 50;//在局部变量中找不到定义的c 沿着作用域链找到了全局变量的c alert('哈哈哈'); functioninner(){ c = 30; alert('嘻嘻'); } inner();//c在函数内部找不到定义 所以沿着作用域链找到了全局的c } varc =20;//到这里一步 m()还没执行 函数没被销毁 这里的c是30 m(); alert(c);//30 

4、object对象

5、面向对象的程序设计

  • a. function 构造器
  • b. prototype 原型
  • c. foreach
  • c.作用域
  • d.继承

一些内存图示

面向对象总结 随笔 第5张

面向对象总结 随笔 第6张

面向对象总结 随笔 第7张

面向对象总结 随笔 第8张

面向对象总结 随笔 第9张

原型链的几张图解

面向对象总结 随笔 第10张

面向对象总结 随笔 第11张

面向对象总结 随笔 第12张

面向对象总结 随笔 第13张

面向对象总结 随笔 第14张

面向对象总结 随笔 第15张

面向对象总结 随笔 第16张

面向对象总结 随笔 第17张

面向对象总结 随笔 第18张

面向对象总结 随笔 第19张

面向对象总结 随笔 第20张

面向对象总结 随笔 第21张

面向对象总结 随笔 第22张

面向对象总结 随笔 第23张

面向对象总结 随笔 第24张

第七课时

上节回顾:

  • 1. switch
  • 2. while/do...while

    • 一般情况下面,如果条件判断是数字的比较 ==<> , for 循环优先.
    • 如果是非数值相关的比较循环, while 优先
  • 3. function 函数

  • 4.代码内存解析
    • 闭包
      • a.程序永远是先定义后执行
      • b.执行永远从上之下
      • c.函数定义的话在堆(只是一个地址而已)
      • d.函数调用的时候,就会有自己的堆和栈(闭包)

知识点:

1、object对象

  • new 关键字代表的是新开辟一块内存空间
  • 没有被引用的内存空间,会在适当的时候被销毁

    • 两句代码含义等同

      • var person = new Object() ;
      • var person = {};
  • 访问对象的属性除了用 对象引用 .属性 key 以外,还可以使用对象引用 [属性key]

new 原理详细解析

  • 无论什么时候,只要创建一个新函数,就会根据一组特定的规则为该函数创建一个prototype 属性,这个属性指向函数的原型对象。
  • 在默认情况下,所有原型对象都会自动获得一个 constructor (构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针(就是指向新创建的函数)。
  • 通过这个构造函数(原型对象的构造函数),可以继续为原型对象添加其他属性和方法。
  • 当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。 ECMA-262 第5版管这个指针叫 [[Prototype]]。脚本中没有标准的方式访问 [[Prototype]] ,但 Firefox 、 Safari 和 Chrome 在每个对象上都支持一个属性 __proto__ ;而在其他实现中,这个属性对脚本是完全不可见的。不过,要明确的真正重要的一点就是,这个连接存在于实例和构造函数的原型对象之间,而不是存在于实例和构造函数之间

new创建对象的步骤

  • 创建一个新的对象
  • 将构造函数的作用域赋给新对象
  • 执行构造函数的代码,为这个新对象添加属性
  • 返回新对象
functionPerson(name, age){
this.name = name;
this.age = age; this.say =function(){ console.log(this.name); }; } functioncreatePerson(P){ // 创建一个新对象 varo =newObject(); // 获取传递给Person函数的参数 varargs =Array.prototype.slice.call(arguments,1); // 新对象的__proto__属性指向Person的原型对象 o.__proto__ = P.prototype; // Person的原型对象的constructor指向Person P.prototype.constructor = P; // 把Person构造函数的作用域赋给新对象 // 给这个新对象添加属性(name,age,say) P.apply(o, args); // 返回这个新对象 returno; } varp = createPerson(Person,'wang',35); 

2、面向对象的程序设计

  • function 构造器

    • 共同点:
      • 动态创建一块内存空间,闭包
    • 不同点:
      • 函数调用是没有办法拿到空间的地址的,而且这块地址是一块临时地址,执行完函数之后,就会销毁
      • new 开辟内存空间,把这块空间的地址返回,这块空间就有可能长期的被引用
  • prototype 原型
    • 通过原型使通过同样一个构造器所 new(创建) 出来的对象具有相同的属性和行为
    • prototype 本质就是一个对象
  • foreach
  • this 指代当前创建的这块内存 this.name=name 指代当前内存中的这个 name 属性 接收外界传过来的值
  • 继承

多种构造函数

传统的创建对象

varperson =newObject();

person.name = “lancer”;

person.age = 24;

person.job = “UI”;

person.sayName = function(){ alert(this.name); } person.sayName(); 

工厂模式

functioncreatePerson(name,age,job){

varo =newObject();

o.name = name;

o.age = age;

o.job = job;

o.sayName = function(){

alert(o.name);

}

returno;

}

varperson1 = createPerson(“lancer”,24,”UI”); person1.sayName(); 

构造函数

functionPerson(name,age,job){

this.name = name;

this.age = age; this.job =job; this.sayName =function(){ alert(this.name) } } varperson1 = createPerson(“lancer”,24,”UI”); person1.sayName(); 

原型模式

functionPerson(){

}

Person.prototype.name =”lancer”;

Person.prototype.age =24; Person.prototype.job = “UI”; Person.prototype.sayName = function(){ alert(this.name) } varperson1 =newPerson(); person1.sayName(); varperson2 =newPerson(); person2.name =”lara” person2.sayName(); 

简单原型模式

functionPerson(){

}

Person.prototype = {

name: “lancer”,

age:24,

job: “UI”,

sayName:function(){ alert(this.name) } }; varperson1 =newPerson(); person1.sayName(); 

构造函数和原型模式

functionPerson(name,age,job){

this.name = name;

this.age = age; this.job =job; } Person.prototype = { constructor:Person, sayName:function(){ alert(this.name) } }; varperson1 =newPerson(“lancer”,”24″,”UI”); person1.sayName(); 

动态原型模式

functionPerson(name,age,job){

this.name = name;

this.age = age; this.job =job; } if(typeofthis.sayName !=”function”){ Person.prototype = { constructor:Person, sayName:function(){ alert(this.name) } }; } varperson1 =newPerson(“lancer”,”24″,”UI”); person1.sayName(); 

稳妥构造函数

varPerson =function(name,age,job){

varO =newObject();

O.sayName = function(){ alert(name); }; returnO } varperson1 = Person(“lancer”,24,”UI”); person1.sayName(); 

其他:

  • 函数调用后一定有返回值,没有返回值就是 undefined

一些内存图示

面向对象总结 随笔 第25张

第八课时

上节回顾:

1.object对象

  • new 关键字代表的是新开辟一块内存空间
  • 没有被引用的内存空间,会在适当的时候被销毁
    • 两句代码含义等同
    • var person = new Object();
    • var person = {};
    • 访问对象的属性除了用 对象引用属性 key 以外,还可以使用对象引用 [属性key]

2.面向对象的程序设计

  • a. function 构造器
    • 共同点:
      • 动态创建一块内存空间,闭包
    • 不同点:
      • 函数调用是没有办法拿到空间的地址的,而且这块地址是一块临时地址,执行完函数之后,就会销毁
      • new 开辟内存空间,把这块空间的地址返回,这块空间就有可能长期的被引用
  • b. prototype 原型
    • 通过原型使通过同样一个构造器所 new (创建)出来的对象具有相同的属性和行为
    • prototype 本质就是一个对象
  • c. foreach
  • c. this
  • d.继承

知识点:

1.prototype内存解析

  • prototype 是原型,是一块所有对应构造器创建的对象都共享的内存空间
  • 在面向对象设计程序的时候,属性应该是对应的空间的,而功能应该是 prototype 公共空间的

2.通过prototype扩展功能

  • 所有的构造器都是继承于 Object 构造器的,因此只要 Object 的原型里有的功能,所有的对象都有
//多个对象的构造 以及 多个对象之间如何建立联系
functionStudent(name,age,sex){
this.name = name; this.age = age; this.sex = sex; } functionBingqilin(name){ this.name = name; } functionGame(name){ this.name = name; } functionHour(time){ this.time = time; } Student.prototype = { eat:function(b){ alert(this.name+"喜欢吃"+b.name); }, mess:function(){ alert(this.name+"的信息:"+this.age+','+this.sex); }, sleep:function(h){ alert(this.name+"每天睡,"+h.time+'小时'); }, work:function(h){ alert(this.name+"每天工作,"+h.time+'小时'); }, like:function(g){ alert(this.name+"喜欢打,"+g.name); } } vars =newStudent("小明",22,"男"); varb =newBingqilin("黑色的冰淇淋"); s.eat(b);//小明喜欢吃黑色的冰淇淋 varg =newGame("英雄联盟"); s.like(g);//把对象的地址发送给like的参数即可访问构造函数Game的name属性 varh =newHour(10); s.sleep(h); s.work(h); 

一些内存图示

面向对象总结 随笔 第26张

面向对象总结 随笔 第27张

第九课时

回顾:

1、prototype内存解析

  • prototype 是原型,是一块所有对应构造器创建的对象都共享的内存空间
  • 在面向对象设计程序的时候,属性应该是对应的空间的,而功能应该是 prototype 公共空间的

2、通过prototype扩展功能

  • 所有的构造器都是继承于 Object 构造器的,因此只要 Object 的原型里有的功能,所有的对象都有
  • 构造器在定义的时候 就默认创建了一个空的原型

3、封装

  • 1:找对象 小头爸爸 大头儿子 饭
  • 2:抽象(类,构造器)
  • 3:创建对象并且建立关系(操作对象)

  • 面向对象例子

//小头爸爸牵着大头儿子的手去吃饭,吃完饭之后,

//小头爸爸背着大头儿子回家,回家后儿子学习,老爸工作,工作学习完后 //儿子看动画片 //围裙妈妈带儿子睡觉 //张三和张四 //分析对象 小头爸爸 大头儿子 饭 以及功能 //设计构造器(类) //创建对象以及他们之间的关联 functionPerson(name,age){ this.name = name; this.age = age; } functionRice(name){ this.name = name; } //Person.prototype.getHand = function(){//这样子写也可以 但还是用默认生成的那块空的内存对象 往里面添加属性 方法 //不浪费内存 //} //在prototype中定义的每个对象都有这些功能 Person.prototype = {//这样子写 抛弃了默认生成的那块空的内存对象 重新创建了一块新的内存对象 记住:原型的本质是对象 //多个功能写在一起 getHand:function(person){//牵手 alert(this.name+"在牵着"+person.name+"的手...."); }, eat:function(rice){ alert(this.name+"在吃"+rice.name); }, //需求 18岁以上才能背人 /* //写法一 不推荐 这个满足18岁的功能是自己强加的 不是客户需求的 carry:function(person){//这里设计不合理 让老爸有这个功能 儿子没有这个功能 if(this.age>=18){ alert(this.name+'背着'+person.name); }else{ alert(this.name+",还未满18岁,背不起"); } },*/ backhome:function(){ alert(this.name+"回家"); }, study:function(){ alert(this.name+"正在学习"); }, watchTV:function(jm){ alert(this.name+"正在看"+jm+'...'); } }; varp1 =newPerson("老爸",20); varp2 =newPerson("儿子",15); //p1.getHand(p2); //p1.eat(new Rice("蛋炒饭")); //p2.eat(new Rice("猪脚饭")); //p1.carry(p2);//老爸背儿子 //p2.carry(p1);//让儿子背老爸 输出结果:儿子,还未满18岁,背不起 //p1.backhome(); //写法二 不推荐 100对关系 代码写很多遍 /* //让老爸单独有背的这个功能 儿子没有这个功能 p1.carry = function(person){ alert(this.name+'背着'+person.name); } p1.carry(p2); */ //-------通过继承解决这个 让老爸单独有背的这个功能 儿子没有这个功能 可以应对多功能 多需求 //功能函数 Object.prototype.extends =function(func,actions){//让所有的子孙 构造器都有这个功能 for(varpropinfunc.prototype){//传进一个func构造器 迭代构造器中的功能 把构造器中的功能全都映射过来 复制一份 this.prototype[prop] = func.prototype[prop];//迭代原型中的所有的功能到 当前里面去 } for(varpropinactions){ this.prototype[prop] = actions[prop]; } }; functionFather(name){ this.name = name; } Father.extends(Person,{ carry:function(person){ alert(this.name+'背着'+person.name); }, work:function(){ alert(this.name+"正在工作"); } }); //扩展 //设计程序有个原则:不修改只增加 functionChildren(name){ this.name = name; } Children.extends(Person); functionMother(name){ this.name = name; } Mother.extends(Person,{ scoop:function(person){ //判断必须是children的对象才能执行这个功能 //if(){ alert(this.name+"唱着摇篮曲哄"+person.name+"睡觉"); //} } }); /* Father.prototype.carry= function(person){//创建这个原型的想法是:原来Person有的功能 我都需要有 并在这些基础上加一个功能 carry //如何建立Father基础Person的功能?写一个继承的小工具来操作 alert(this.name+'背着'+person.name); }; Father.prototype.work = function(){ alert(this.name+"正在工作"); } */ varp1 =newFather("老爸"); varp2 =newChildren("儿子"); p1.carry(p2);//只有老爸有carry这个功能 //p2.carry(p1);//error 儿子没有carry这个功能 p2.study();//儿子在学习 p1.work();//老爸在工作 p1.watchTV('看足球'); p2.watchTV('蜡笔小新'); varp3 =newMother('围裙妈妈'); p3.scoop(p2); 

知识点:

  • 1.继承
  • 2.面向对象程序设计案例(猜拳)

一些内存图示

面向对象总结 随笔 第28张

面向对象总结 随笔 第29张

面向对象总结 随笔 第30张

面向对象总结 随笔 第31张

第十课时

上节回顾:

1.继承

  • 本质就是从一个 prototype 对象中把它的功能都 copy 到另一个 prototype 对象
  • 继承为什么要循环

2.call apply方法的使用

  • func.call(obj) :调用 func 的时候,以 obj 这个对象的作用域去调用
  • 改变函数在调用的时候里面闭包的作用域
  • call(obj,arg1,arg2,arg3) ; call 第一个参数传对象,可以是 null 。参数以逗号分开进行传值,参数可以是任何类型。 
    apply(obj,[arg1,arg2,arg3]) ; apply 第一个参数传对象,参数可以是数组或者arguments 对象

知识点:

API application program interface

  • 第一:遇到问题
  • 第二:查资料或者学习 -> 解决问题
  • 第三:记住有这个功能
  • 第四:查资料(百度)

常用API

  • 1. String
  • 2. Array
  • 3. Math Math.random();
  • 4. Date

日期型函数 Date

面向对象总结 随笔 第32张

  • 声明
varmyDate =newDate();//系统当前时间 varmyDate =newDate(yyyy, mm, dd, hh, mm, ss); varmyDate =newDate(yyyy, mm, dd); varmyDate =newDate(“monthName dd, yyyy hh:mm:ss”); varmyDate =newDate(“monthName dd, yyyy”); varmyDate =newDate(epochMilliseconds); 
  • 获取时间的某部份
varmyDate =newDate();

myDate.getYear(); //获取当前年份(2位)

myDate.getFullYear(); //获取完整的年份(4位,1970-????) myDate.getMonth(); //获取当前月份(0-11,0代表1月) myDate.getDate(); //获取当前日(1-31) myDate.getDay(); //获取当前星期X(0-6,0代表星期天) myDate.getTime(); //获取当前时间(从1970.1.1开始的毫秒数) 时间戳!! myDate.getHours(); //获取当前小时数(0-23) myDate.getMinutes(); //获取当前分钟数(0-59) myDate.getSeconds(); //获取当前秒数(0-59) myDate.getMilliseconds(); //获取当前毫秒数(0-999) myDate.toLocaleDateString(); //获取当前日期 myDate.toLocaleTimeString(); //获取当前时间 myDate.toLocaleString( ); //获取日期与时间 
  • 计算之前或未来的时间
varmyDate =newDate();

myDate.setDate(myDate.getDate() + 10);//当前时间加10天//类似的方法都基本相同,以set开头,具体参考第2点 
  • 计算两个日期的偏移量
vari = daysBetween(beginDate,endDate);//返回天数 vari = beginDate.getTimezoneOffset(endDate);//返回分钟数 
  • 检查有效日期
//checkDate() 只允许”mm-dd-yyyy”或”mm/dd/yyyy”两种格式的日期
if( checkDate(“2006-01-01”) ){ } //正则表达式(自己写的检查 yyyy-mm-dd, yy-mm-dd, yyyy/mm/dd, yy/mm/dd 四种) varr =/^(\d{2}|\d{4})[\/-]\d{1,2}[\/-]\d{1,2}$/;if( r.test( myString ) ){ } 

字符串String型函数API

面向对象总结 随笔 第33张

  • 声明
varmyString =newString(“Every good boy does fine.”); varmyString = “Every good boy does fine.”; 
  • 字符串连接
varmyString = “Every ” + “good boy ” + “does fine.”; varmyString = “Every “; myString += “good boy does fine.”; 
  • 截取字符串
//截取第 6 位开始的字符

varmyString = “Every good boy does fine.”;

varsection = myString.substring(6);//结果: “good boy does fine.” //截取第 0 位开始至第 10 位为止的字符 varmyString = “Every good boy does fine.”; varsection = myString.substring(0,10);//结果: “Every good” //截取从第 11 位到倒数第 6 位为止的字符 varmyString = “Every good boy does fine.”; varsection = myString.slice(11,-6);//结果: “boy does” //从第 6 位开始截取长度为 4 的字符 varmyString = “Every good boy does fine.”; varsection = myString.substr(6,4);//结果: “good” 
  • 转换大小写
varmyString = “Hello”; varlcString = myString.toLowerCase();//结果: “hello” varucString = myString.toUpperCase();//结果: “HELLO” 
  • 字符串比较
varaString = “Hello!”;

varbString =newString(“Hello!”);

if( aString == “Hello!” ){ }//结果: true if( aString == bString ){ }//结果: true if( aString === bString ){ }//结果: false (两个对象不同,尽管它们的值相同) 
  • 检索字符串
varmyString = “hello everybody.”;

// 如果检索不到会返回-1,检索到的话返回在该串中的起始位置

if( myString.indexOf(“every”) >-1){ }//结果: true 
  • 查找替换字符串
varmyString = “I is your father.”; varresult = myString.replace(“is”,”am”);//结果: “I am your father.” 
  • 特殊字符

    • \b : 后退符
    • \t : 水平制表符
    • \n : 换行符
    • \v : 垂直制表符
    • \f : 分页符
    • \r : 回车符
    • \” : 双引号
    • \’ : 单引号
    • \\ 反斜杆
  • 将字符转换成 Unicode 编码
varmyString = “hello”; varcode = myString.charCodeAt(3);//返回”l”的Unicode编码(整型) varchar =String.fromCharCode(66);//返回Unicode为66的字符 
  • 将字符串转换成URL编码
varmyString = “hello all”;

varcode =encodeURI(myString);//结果: “hello%20all”

varstr =decodeURI(code);//结果: “hello all” //相应的还有: encodeURIComponent() decodeURIComponent() 

Math对象型

  • Math.abs(num) : 返回 num 的绝对值

  • Math.acos(num) : 返回 num 的反余弦值

  • Math.asin(num) : 返回 num 的反正弦值

  • Math.atan(num) : 返回 num 的反正切值

  • Math.atan2(y,x) : 返回 y 除以 x 的商的反正切值

  • Math.ceil(num) : 返回大于 num 的最小整数

  • Math.cos(num) : 返回 num 的余弦值

  • Math.exp(x) : 返回以自然数为底,x次幂的数

  • Math.floor(num) : 返回小于 num 的最大整数

  • Math.log(num) : 返回 num 的自然对数

  • Math.max(num1,num2) : 返回 num1 和 num2 中较大的一个

  • Math.min(num1,num2) : 返回 num1 和 num2 中较小的一个

  • Math.pow(x,y) : 返回 x 的 y 次方的值

  • Math.random() : 返回 0 到 1 之间的一个随机数

  • Math.round(num) : 返回 num 四舍五入后的值

  • Math.sin(num) : 返回 num 的正弦值

  • Math.sqrt(num) : 返回 num 的平方根

  • Math.tan(num) : 返回 num 的正切值

  • Math.E : 自然数( 2.718281828459045 )

  • Math.LN2 : 2 的自然对数( 0.6931471805599453 )

  • Math.LN10 : 10 的自然对数( 2.302585092994046 )

  • Math.LOG2E : log 2 为底的自然数( 1.4426950408889634 )

  • Math.LOG10E : log 10 为底的自然数( 0.4342944819032518 )

  • Math.PI : π(3.141592653589793)

  • Math.SQRT1_2 : 1/2 的平方根( 0.7071067811865476 )

  • Math.SQRT2 : 2 的平方根( 1.4142135623730951 )

Number型 常用的数字函数

  • 声明
vari =1; vari =newNumber(1); 
  • 字符串与数字间的转换
vari =1;

varstr = i.toString();//结果: “1” varstr =newString(i);//结果: “1” i = parseInt(str);//结果: 1 i = parseFloat(str);//结果: 1.0 //注意: parseInt,parseFloat会把一个类似于”32G”的字符串,强制转换成32 
  • 判断是否为有效的数字
vari =123;varstr = “string”; if(typeofi == “number” ){ }//true //某些方法(如:parseInt,parseFloat)会返回一个特殊的值NaN(Not a Number) //请注意第2点中的[注意],此方法不完全适合判断一个字符串是否是数字型!! i = parseInt(str); if(isNaN(i) ){ } 
  • 数字型比较
//此知识与[字符串比较]相同

- **小数转整数**

varf =1.5; vari =Math.round(f);//结果:2 (四舍五入) vari =Math.ceil(f);//结果:2 (返回大于f的最小整数) vari =Math.floor(f);//结果:1 (返回小于f的最大整数) 
  • 格式化显示数字
vari =3.14159;

//格式化为两位小数的浮点数 varstr = i.toFixed(2);//结果: “3.14” //格式化为五位数字的浮点数(从左到右五位数字,不够补零) varstr = i.toPrecision(5);//结果: “3.1415” 
  • X进制数字的转换
vari =parseInt(“0x1f”,16); vari =parseInt(i,10); vari =parseInt(“11010011”,2); 
  • 随机数
//返回0-1之间的任意小数

varrnd =Math.random();

//返回0-n之间的任意整数(不包括n) varrnd =Math.floor(Math.random() * n) 

5. Regex

//在这个最大的对象的原型上加一个extends方法 使得下面所有的原型 都有这个方法
//这个原型的作用是通过迭代 复制传进来的构造器的所有的原型的方法 Object.prototype.extends =function(parent){ //console.log(parent.prototype); for(varpropinparent.prototype){ //console.log(prop);//eat extends this.prototype[prop] = parent.prototype[prop];//复制传进来的构造器的所有的原型的方法给当前正在调用这个方法的对象 } } functionPerson(name){ this.name = name; } Person.prototype = { eat:function(){ alert(this.name+"在吃饭"); } }; functionFather(name){ this.name = name; } Father.extends(Person);//extends方法是最大的对象Object加的方法 所有的子孙 构造器都有这个方法 varf =newFather("小头爸爸"); f.eat(); 

一些图示

面向对象总结 随笔 第34张

面向对象总结 随笔 第35张

第十一课时

上节回顾:

  • 1. String
  • 2. Math Math.random()

知识点:

  • 1. Date 日期类
  • 2. Array
  • 3. Regex
    • a. [] 一个字符的范围
    • b.有顺序要求的
    • c. \w==[a-zA-Z0-9_] \d==[0-9]
    • d. {count} 设置匹配数量比如 \w{5}
    • e. // 的正则表达式匹配局部, /^$/ 的正则表达式是匹配全部
    • f. () 的作用就是为了分组匹配
  • 简单封装一个对象案例
String.prototype.isEmail =function(){

 email = this;
if(email.indexOf("@")!=-1&&email.indexOf(".")!=-1) { if(email.indexOf("@")<email.lastIndexOf("@")){ alert("邮箱不合法"); }else{ alert("邮箱合法"); } } } varemail ="jingguanliuye@gmail.com"; email.isEmail(); 
//===============================日历练习(方法简洁 高效)======================================

//var year = parseInt(prompt("请输入日历年份:"));
//var month = parseInt(prompt("请输入日历月份:"))-1;

Date.prototype.printCalendar =function(){

varyear =this.getFullYear(),month =this.getMonth();
vardate =newDate(year,month,1);

//alert(date.toLocaleString());
document.write("<div class='date'>"+year+"年"+(month+1)+"月</div>"); document.write("日 一 二 三 四 五 六<br />"); varday = date.getDay(); for(vari=0;i<day;i++){ document.write(' '); } varcount =newDate(year,month+1,0).getDate();//这里的0返回一个月的最后一天 for(vari=1;i<=count;i++){ document.write(i+' '); if((i+day)%7==0){ document.write('<br/>'); } } } newDate(2012,2).printCalendar(); 

第十二课时

上节回顾:

  • 1. Date 期类
  • 2. Array
  • 3. Regex
    • a. [] 一个字符的范围
    • b.有顺序要求的
    • c. \w==[a-zA-Z0-9_] \d==[0-9]
    • d. {count} 设置匹配数量比如 \w{5} , {c1,c2}
    • e. // 的正则表达式匹配局部, /^$/ 的正则表达式是匹配全部
    • f. () 的作用就是为了分组匹配

新知识点:

  • 1. Regex
    • g. + 代表的是 1-N 个, * 代表的是 0-N 个
    • h. ? 代表该字符要不没有要不就有一个
    • i. . 代表的是任意字符
    • j. \转义符
  • 2. BOM

第十三课时

上节回顾:

  • 1.Regex
    • a. [] 一个字符的范围
    • b.有顺序要求的
    • c. \w==[a-zA-Z0-9_] \d==[0-9]
    • d. {count} 设置匹配数量比如 \w{5} , {c1,c2}
    • e. // 的正则表达式匹配局部, /^$/ 的正则表达式是匹配全部
    • f. () 的作用就是为了分组匹配
    • g.+代表的是 1-N 个, * 代表的是 0-N 个
    • h. ? 代表该字符要不没有要不就有一个
    • i. . 代表的是任意字符
    • j. \转义符

新知识:

  • window 是 Window 构造器造出来的一个对象 alert(window instanceof Window)
  • document 是 Document 构造器造出来的一个对象
  • 任何对象在我们的内存中他都是由某个构造器创建出来的 也就是说 有构造器一定有对应的原型prototype
  • 例如: div 是由 HTMLDivElement 这个构造器创建的一个实例 div = new HTMLDivElement() span = new HTMLSpanElement()
  • 查看某个对象对应的构造器: console.log();
  • 整个浏览器的实现就是一个面向对象的编程思想 一切皆是对象

1.BOM 浏览器对象模型

面向对象总结 随笔 第36张

  • a. screen 指的不是浏览器的宽度,指的是整个电脑屏幕的分辨率
    • 可以拿到屏幕可用分辨率
  • b. navigator
    • 可以通过 userAgent 判断当前浏览器信息
  • c. location
    • URL :统一资源定位符 Union Resource Location
    • 可以通过 href 属性重定向(改变)页面的URL,进行页面跳转
  • d. history
    • go 方法能够让我们进行历史回退或者前进
  • e. frames

    • 获得当前窗体的子页面( iframe )
  • f. document

    • DOM 模型的核心对象

2. DOM 文档对象模型

  • document

    • 功能
      • getElementById $('#aaa')
      • getElementByTagName $('div')
      • getElementsByClassName $('.aaa')
      • getElementsByName 只用在表单元素中
  • document object

    • 属性:
      • className , style
      • id
      • name , value (表单元素)
      • href , src …(对应的元素)
      • innerHTML
      • children
      • parentNode
    • 功能方法:
      • setAttribute/getAttribute
      • appendChild

第十四课时

上节回顾:

  • 1.BOM 浏览器对象模型
    • a. screen 指的不是浏览器的宽度,指的是整个电脑屏幕的分辨率
      • 可以拿到屏幕可用分辨率
    • b. navigator
      • 可以通过 userAgent 判断当前浏览器信息
    • c. location
      • URL :统一资源定位符 Union Resource Location
      • 可以通过 href 属性重定向(改变)页面的URL,进行页面跳转
    • d. history
      • go 方法能够让我们进行历史回退或者前进
    • e. frames
      获得当前窗体的子页面(`iframe`)
    • f. document
      • DOM 模型的核心对象
  • 所有的 DOM 对象都是在堆内存创建的 都是有一个构造器生成的
  • 查看对象的构造器器方法:
    • step1:查看标签的对象以及构造器 var body = document.body;console.log(body.toString())
    • step2:查看对象是否是这个构造器创建出来的 console.log(body instanceof HTMLBodyElement)

新知识点:

1.DOM 文档对象模型

document

  • 功能
    • getElementById :通过传入的ID,返回标识了这个ID的唯一对象的内存地址
    • getElementsByTagName :通过传入的标签名字,返回所有该标签对象( HTMLCollection )
    • getElementsByClassName :通过类的名字,返回所有该类的元素对象( HTMLCollection )
    • createElement :想要创建出来的元素能够绘制在页面中,那么它必须在DOM树中
      • 总结 document 对象是DOM原型的核心对象,它是内存DOM树的根,所以它提供了很多功能让我们快速的找到DOM树中的某些DOM节点(对象)

element

  • 功能方法:(自定义属性非常灵活好用)

    • setAttribute/getAttribute //getAttribute获取标签的属性 –用来操作标签的属性
    • setAttribute 设置标签的属性
    • appendChild :添加子元素
  • 属性:

    • id
    • className , style
    • name , value (只有表单元素有 其他是没有的)
    • href , src …(对应的元素)
    • innerHTML/innerText innerText 返回文本信息
    • children ://子元素集合
    • parentNode //父元素
  • 总结:元素的功能属性直接可以通过元素对象  出来,除此意外的 自定义属性,请通过 get/setAtribute 去操作

DOM 操作:

  • 图片切换的相册效果
  • tab 切换效果
  • 表单验证
  • 特效就是 DOM 操作的具体应用 DOM 操作就是用 js 来写 HTML 代码
  • 节点/元素/标签:
    • 三种常用的节点类型:
      • 元素节点
      • 属性节点
      • 文本节点

操作DOM对象:

  • 修改:–找到这个节点
  • 删除:–找到这个节点
  • 添加:–先造出一个节点 然后插入 插入到哪里?找节点来定位
  • 这些都离不开节点的查找

节点的查找:(最重要)

  • 1、 document.getElementById —根据 id 查找节点 [返回的是节点本身]
  • 2、 document.getElementsByTagName –根据标签名字来查找[返回的是数组] document.getElementsByTagName[i]
  • 3、 document.getElemenstByName –根据 name 属性来查找节点(一般用在表单中)[返回的是数组] document.getElemenstByName[i]
  • 注意:早期浏览器都认为 name 只出现在表单中

  • 因此 document.getElemenstByName 只对表单中的元素发挥作用 后来部分浏览器把 Name 属性扩展到一般的元素 如: div 但是IE浏览器还是只能对表单使用 byName 因此处于兼容性 我们只能对表单使用 byName

DOM 中查找节点的思路:(由大到小 个别情况 由子到父)

  • 由大到小:(通过下面的来定位)

    • 1、 document.getElementById —根据id查找节点 [返回的是节点本身]
    • 2、 document.getElementsByTagName –根据标签名字来查找[返回的是数组] document.getElementsByTagName[i]
    • 3、 document.getElemenstByName –根据 name 属性来查找节点(一般用在表单中)[返回的是数组] document.getElemenstByName[i]
  • 如果还没有查到自己想要的节点,还可以继续根据上面已经找到的节点再次定位来查找
  • 怎么继续定位?
    • 答: childNodes/child

继续查找:

  • 1、查找子元素 children[index]/childNodes
  • 2、查找父元素 node.parentNode –>获取父元素
  • 3、查找兄弟元素 nextSibling previousSibling
  • 4、 nextSibling previousSibling firstChild lastChild 这四个属性容易受到 空白文本 的影响 建议不用
//============给Object原型加一个方法 消除文本节点对DOM操作的影响 例如:nextSibling` `previousSibling` `firstChild` `lastChild (受到换行 和文本节点影响)

Object.prototype.next =function(){ //NodeType == 3 text的代号 //NodeType == 1 tag的代号 if(this.nextSibling){//判断下一个兄弟节点是否存在 switch(this.nextSibling.nodeType){ case1: returnthis.nextSibling; case3: returnthis.nextSibling.nextSibling; } }else{ returnnull; } console.log(div1.next().next().innerText); 
  • 5、对于查到的某个元素里面的子元素非常多 这时候还可利用 getElementsByTagname 进一步筛选

  • 注意对于元素对象和 document 对象相比 元素对象只能利用 getElementsByTagName 函数 其他两个不能用

  • 节点查找也是通过由大到小来定位:找到大的元素进一步细化 完全可以找到页面上任意一个元素控制他

  • 子元素 不好找 就找他的父元素

  • 要过滤空白文本节点,用 children 取他的文本节点

DOM与节点的关系:

  • node:
    • childNodes[]
    • parentNode
    • firstChild
    • getElementsByTagName('元素标签')
    • lastchild
    • nextSibling
    • previousSibling
    • children[index] children 不是 w3c 标准 但是各大浏览器兼容性很好
  • 通过给原型添加方法在元素后面创建标签

  • 启示:在项目中,很多很多地方都需要一个方法但是系统没提供,这时可以通过原型扩展

//var p = document.createElement('p');
//p.innerHTML = "this is a p"; //var child = document.getElementsByTagName('div'); //给Div的HTMLDivElement构造器原型加一个创建元素的方法 要所有的元素都有这个方法 改成 Object HTMLDivElement.prototype.createElement = function(tagName){ varchild =document.createElement(tagName); this.appendChild(child); returnchild; } varchild =document.getElementsByTagName('div')[2].createElement("p"); child.innerHTML = 'pppppp'; 

DOM属性小结

  • Attributes 存储节点的属性列表(只读)

  • childNodes 存储节点的子节点列表(只读)

  • dataType 返回此节点的数据类型

  • Definition 以 DTD 或 XML 模式给出的节点的定义(只读)

  • Doctype 指定文档类型节点(只读)

  • documentElement 返回文档的根元素(可读写)

  • firstChild 返回当前节点的第一个子节点(只读)

  • Implementation 返回 XMLDOMImplementation 对象

  • lastChild 返回当前节点最后一个子节点(只读)

  • nextSibling 返回当前节点的下一个兄弟节点(只读)

  • nodeName 返回节点的名字(只读)

  • nodeType 返回节点的类型(只读)

  • nodeTypedValue 存储节点值(可读写)

  • nodeValue 返回节点的文本(可读写)

  • ownerDocument 返回包含此节点的根文档(只读)

  • parentNode 返回父节点(只读)

  • Parsed 返回此节点及其子节点是否已经被解析(只读)

  • Prefix 返回名称空间前缀(只读)

  • preserveWhiteSpace 指定是否保留空白(可读写)

  • previousSibling 返回此节点的前一个兄弟节点(只读)

  • Text 返回此节点及其后代的文本内容(可读写)

  • url 返回最近载入的XML文档的 URL (只读)

  • Xml 返回节点及其后代的 XML 表示(只读)

DOM方法小结

  • cloneNode 返回当前节点的拷贝
  • createAttribute 创建新的属性
  • 节点操作 DOMDocument 属性和方法

    • createCDATASection 创建包括给定数据的 CDATA 段

    • createComment 创建一个注释节点

    • createDocumentFragment 创建 DocumentFragment 对象

    • createElement_x_x 创建一个元素节点

    • createEntityReference 创建 EntityReference 对象

    • createNode 创建给定类型,名字和命名空间的节点

    • createPorcessingInstruction 创建操作指令节点

    • createTextNode 创建包括给定数据的文本节点

    • getElementsByTagName 返回指定名字的元素集合

    • hasChildNodes 返回当前节点是否有子节点

    • insertBefore 在指定节点前插入子节点

    • Load 导入指定位置的XML文档

    • loadXML 导入指定字符串的XML文档

    • removeChild 从子结点列表中删除指定的子节点

    • replaceChild 从子节点列表中替换指定的子节点

    • Save 把 XML`文件存到指定节点

    • selectNodes 对节点进行指定的匹配,并返回匹配节点列表

    • selectSingleNode 对节点进行指定的匹配,并返回第一个匹配节点

    • transformNode 使用指定的样式表对节点及其后代进行转换

    • transformNodeToObject 使用指定的样式表将节点及其后代转换为对象

    • document.documentElement 返回文档的根节点

    • document.activeElement 返回当前文档中被击活的标签节点

    • event.fromElement 返回鼠标移出的源节点

    • event.toElement 返回鼠标移入的源节点

    • event.srcElement 返回激活事件的源节点

    • node.parentNode,node.parentElement 返回父节点

    • node.childNodes 返回子节点集合(包含文本节点及标签节点)

    • node.children 返回子标签节点集合

    • node.textNodes 返回子文本节点集合

    • node.firstChild 返回第一个子节点

    • node.lastChild 返回最后一个子节点

    • node.nextSibling 返回同属下一个节点

    • node.previousSibling 返回同属上一个节点

    • node.a(oNode) 追加子节点:

    • node.applyElment(oNode,sWhere)

    • sWhere 有两个值: outside / i nside 应用标签节点

    • node.insertBefore()

    • node.insertAdjacentElement()

    • node.replaceAdjacentText()

  • 插入节点

    • node.remove()
    • node.removeChild()
    • node.removeNode()
  • 删除节点

    • node.replaceChild()
    • node.replaceNode()
    • node.swapNode()
  • 替换节点

    • node.cloneNode(bAll) 返回复制复制节点引用
    • node.contains() 是否有子节点
    • node.hasChildNodes() 是否有子节点

第十五课时

上节回顾:

1.DOM 文档对象模型

document

  • 功能
    • getElementById :通过传入的ID,返回标识了这个ID的唯一对象的内存地址
    • getElementsByTagName :通过传入的标签名字,返回所有该标签对象( HTMLCollection )
    • getElementsByClassName :通过类的名字,返回所有该类的元素对象( HTMLCollection )
    • createElement :想要创建出来的元素能够绘制在页面中,那么它必须在DOM树中
      • 总结: document 对象是DOM原型的核心对象,它是内存DOM树的根,所以它提供了很多功能让我们快速的找到DOM树中的某些DOM节点(对象)
  • element
    • 功能方法:(自定义属性非常灵活好用)
      • setAttribute/getAttribute //getAttribute获取标签的属性 –用来操作标签的属性
      • setAttribute 设置标签的属性
      • appendChild :添加子元素
    • 属性:
      • id
      • className , style
      • name , value (只有表单元素有 其他是没有的)
      • href , src …(对应的元素)
      • innerHTML/innerText innerText返回文本信息
      • children ://子元素集合
      • parentNode //父元素
      • 总结:元素的功能属性直接可以通过元素对象  出来,除此意外的 自定义属性 ,请通过 get/setAtribute 去操作

新知识点:

1.事件(事故)基础

  • 白话含义:就是当一个事物遇到某个事情的时候,要做的事情
    • (事件源)
    • (事件监听名称)
    • (事件处理程序)

2.常用事件

  • onclick: 当事件源被点击的时候调用处理程序
  • onmouseover: 鼠标进入事件
  • onmouseout: 鼠标移出事件
  • onmousedown: 鼠标按下去的时候
  • onmouseup: 鼠标抬起来的时候
  • onscroll: 当事件源滚动条滚动的时候
  • onkeydown: 当键盘按下的时候
  • onkeypress: 当键盘按下去的时候
  • onkeyup: 当键盘弹上来的时候
  • onfocus: 当事件源获得光标
  • onblur: 当事件源失去光标
  • onchange: 当事件源 blur 的时候内容改变了的话

浏览器事件注意事项:

  • 1.以后我们不要把事件写在标签上,而使用 js 方式操作
  • 2.js方式操作的话:
    • 非 IE 浏览器第一个对象就会传入 event 事件源对象
    • IE浏览器第一个对象就不会传入 event 事件源对象( event = event||window.event ;)
    • 非 IE 浏览器的事件源属性是 target 属性( event.target = event.target||event.srcElement ;)
    • IE 浏6览器的事件源属性是 srcElement 属性
  • 3.事件冒泡机制
  • 4.案例

总结

  • 以上是一些很基础的理论,笔记经验终究是别人的,看完了还是会忘记的,要转化成自己的东西,还要靠你不断实践。

面向对象总结 随笔 第37张

  • JavaScript 读书路线

面向对象总结 随笔 第38张

php面向对象

一、面向对象的基本概念
  1.什么是面向对象?
    对象
    面向

     由于目前都还没有一个统一的概念,所以所能理解的就是一个物体被抽象出来,每个物品都是一个对象。

  2.什么是对象?
    ---世间万物皆对象
    桌子、人、键盘……
    看见的,看不见的(抽象的)

  3.对象的基本组成
    对象包含两部分
      -对象的组成元素
        ·是对象的数据模型,用于描述对象的数据
        ·又被称为对象的属性,或者对象的成员变量
      -对象的行为
        ·是对象的行为模型,用于描述对象能够做什么事情
        ·又被称为对象的方法

  4.对象的特点
    ·每个对象都是独一无二的
    ·对象是一个特定事务,他的职能是完成特定功能
    ·对象是可以重复使用的

  5.面向对象编程的基本概念
    ·什么是面向对象?
    -面向就是在编程的时候一直把对象放在心上
      ·面向对象编程就是在编程的时候数据结构(数据组织方式)都通过对象的结构进行存储
    -属性、方法

      ·对象的描述方式更加贴合真实的世界,有利于大型业务的理解
      ·在程序设计的过程中用对象的视角分析世界的时候能够独立拉近程序设计和真实世界的距离

  6.面向对象--实质
    ·面向对象就是把生活中要解决的问题都用对象的方式进行存储
      -属性
      -方法
    ·对象与对象之间通过方法的调用完成互动
      -方法

  7.面向对象的基本思路
    第一步:识别对象
      -任何实体都可以被识别为一个对象
    第二步:识别对象的属性
      -对象里面存储的数据被识别为属性
      -对于不同的业务逻辑,关注的数据不同,对象里面存储的属性也不同
    第三步:识别对象的行为
      -对象自己属性数据的改变
      -对象和外部交互

 

  8.面向对象的基本原则
    对象内部是高内聚的
      -对象只负责一项特定的职能(职能可大可小)
      -所有对象相关内容都封装到对象的内部
    对象度外是低耦合的
      -外部世界可以看到对象的一些属性(并非全部)
      -外部世界可以看到对象可以做某些事情(并非全部)

二、PHP中的面向对象编程
    1.面向对象基本实践
      类的概念
      -类以物聚,把具有相似特性的对象归类到一个类中
      -类定义了这些相似对象拥有的相同的属性和方法
      -类是相似对象的描述,称为类的定义,是该类对象的蓝图或者原型
      -类的对象称为类的一个实例(类的实例化)
      -类的属性和方法统称为类成员

    2.类的实例化
      类的实例化就是通过类定义创建一个类的对象

      类的定义里面属性值都是空的,而对象的属性都具有具体的值

实例:
// 类的定义以关键字class开始,后面跟着这个类的名称。类的命名通常每个单词的第一个字母大写。以中括号开始和结束

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 <?php date_default_timezone_set( "PRC" ); // 类的定义以关键字class开始,后面跟着这个类的名称。类的命名通常每个单词的第一个字母大写。以中括号开始和结束      class  NbaPlayer{          public  $name = "Jordan" ;          public  $height = "198cm" ;          public  $weight = "98kg" ;          public  $team = "bull" ;          public  $playerNumber = "23" ;            // 默认构造函数,在对象被实例化的时候自动调用      function  __construct( $name , $height , $weight , $team , $playerNumber ){          echo  "In NbaPlayer constructor <br>" ;          $this ->name = $name ; //$this是php里面的伪变量,表示对象自身。可以通过$this->的方式访问对象的属性和方法          $this ->height= $height ;          $this ->weight= $weight ;          $this ->team= $team ;          $this ->playerNumber= $playerNumber ;      }            // 定义方法      public  function  run(){          echo  "Running\n" ;      }      public  function  jump(){          echo  "Jumping\n" ;      }      public  function  dribble(){          echo  "dribbling\n" ;      }      public  function  shoot(){          echo  "shooting\n" ;      }      public  function  dunk(){          echo  "dunking\n" ;      }      public  function  pass(){          echo  "passing\n" ;      }        // 析构函数,在程序执行结束的时候会自动调用      //析构函数通常被用于清理程序使用的资源。比如程序使用了打印机,那么可以在析构函数里面释放打印机资源      function  __destruct(){          echo  "Destroying " . $this ->name. "<br>" ;      }        }      //类到对象的实例化      // 类的实例化为对象使用关键字new,new之后紧跟类的名称和一对括号      $Jordan = new  NbaPlayer( "lihua" , "198cm" , "98kg" , "bull" , "23" );      // 对象中的属性成员可以通过->符号来访问      echo  $Jordan ->name. "<br>" ;      echo  $Jordan ->height. "<br>" ;      // 对象中的成员方法可以通过->符号来访问      $Jordan ->dribble();      $Jordan ->pass(). "<br>" ;            $james = new  NbaPlayer( "James" , "213cm" , "100kg" , "heat" , "23" );      echo  $james ->name. "<br>" ;      //通过把变量设置为null 可以触发析构函数的调用      $james =null;      echo  "From now on james will not be used<br>" ; ?>

 

三、面向对象高级实践
  1.面向对象--继承
    继承的好处:
     -父类里面定义的类成员可以不用在子类中重复定义,节约了编程的时间和代价
      ·比如,人的吃这个方法一旦在父类汇总定义,那么NBA球员和女主播两个子类就不需要实现吃这个方法了,就好像天胜就有这个功能一样
      -同一个父类的子类拥有相同的父类定义的类成员,因此外部代码调用它们的时候可以一视同仁
      ·比如 一个NBA球员和一个女主播,因为她们都是人,所以可以直接调用父类定义的“吃”方法,而不用管他到底是个NBA球员还是女主播
     -子类可以修改和调整父类定义的类成员
      ·我们称为重写
    ·一旦子类修改了,就按照子类修改之后的功能执行

实例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?php class  Human{ public  $name ; public  $height ; public  $weight ;   function  eat( $food ){ echo  $this ->name. "'s eating " . $food . "<br>" ; } } //在PHP中可以使用extends关键字来表示类的继承,后面跟父类的类名 // PHP在extends后面只能跟一个类的类名,这就是PHP的单继承原则 class  NbaPlayer  extends  Human{ public  $team ; public  $playerNumber ; function  __construct( $name , $height , $weight , $team , $playerNumber ){ $this ->name = $name ; $this ->height= $height //父类中的属性,可以通过$this来访问 $this ->weight= $weight ; $this ->team= $team ; $this ->playerNumber= $playerNumber ; }   } $Jordan = new  NbaPlayer( "jordan" , "198cm" , "98kg" , "bull" , "23" ); echo  $Jordan ->name. "<br>" ; $Jordan ->eat( "chicken" );  //在子类的对象上可以直接访问父类中定义的方法和属性 ?>

  

  2.面向对象--访问控制

    ·面向对象的三种访问权限
      -public公有的类成员,可以在任何地方被访问
    ·定义该成员的类(自身)、该类的子类、其他类
      -protected受保护的类成员,可以被其自身以及其子类访问
      -private私有的类成员,只能被自身访问

     //在大括号内的保护对象或是私有对象是可以随便访问的,但是不能在类的外面直接引用
实例:

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 <?php          class  Human{              public  $name ;              protected  $height //自身和子类可以访问              public  $weight ;              private  $human =true;   //只能自身访问                            function  eat( $food ){                  echo  $this ->name. "'s eating " . $food . "<br>" ;              }              // 可以这样让子类调用私有和保护的对象,这叫封装              public  function  info(){                  echo  $this ->name. ";" . $this ->height. ";" . $this ->human. "<br>" ;              }            }          class  NbaPlayer  extends  Human{              public  $team = "bull" ;              public  $playerNumber = "23" ;              private  $age = "38" ;            // 默认构造函数,在对象被实例化的时候自动调用          function  __construct( $name , $height , $weight , $team , $playerNumber ){              echo  "In NbaPlayer constructor <br>" ;              $this ->name = $name ; //$this是php里面的伪变量,表示对象自身。可以通过$this->的方式访问对象的属性和方法              $this ->height= $height //父类中的属性,可以通过$this来访问              $this ->weight= $weight ;              $this ->team= $team ;              $this ->playerNumber= $playerNumber ;          }          function  getAge(){              echo  $this ->name. "'s age is " . $this ->age. "<br>" ;          }            }          //类到对象的实例化          // 类的实例化为对象使用关键字new,new之后紧跟类的名称和一对括号          $Jordan = new  NbaPlayer( "jordan" , "198cm" , "98kg" , "bull" , "23" );          echo  $Jordan ->name. "<br>" ;          $Jordan ->eat( "chicken" );  //在子类的对象上可以直接访问父类中定义的方法和属性          $Jordan ->getAge();          // echo $Jordan->height; //保护对象这样不能访问          $Jordan ->info();   ?>

  

   3.面向对象--静态成员
    使用类的静态成员特性就可以达到这样的效果
    -static关键字

实例:

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 <?php /*      1.静态属性用于保存类的共有数据      2.静态方法里面只能访问静态属性      3.静态成员不需要实例化对象就可以访问      4.类的内部可以通过self 或者static关键字访问自身静态成员      5.可以通过parent关键字访问父类的静态成员      6.可以通过类的名称在类定义外部访问静态成员 */      class  Human{          public  $name ;          protected  $height //自身和子类可以访问          public  $weight ;          private  $human =true;   //只能自身访问                    public  static  $sValue  "this is parent static" ;          function  eat( $food ){              echo  $this ->name. "'s eating " . $food . "<br>" ;          }          // 可以这样让子类调用私有和保护的对象,这叫封装          public  function  info(){              echo  $this ->name. ";" . $this ->height. ";" . $this ->human. "<br>" ;          }        }      //在PHP中可以使用extends关键字来表示类的继承,后面跟父类的类名      // PHP在extends后面只能跟一个类的类名,这就是PHP的单继承原则 // 类的定义以关键字class开始,后面跟着这个类的名称。类的命名通常每个单词的第一个字母大写。以中括号开始和结束      class  NbaPlayer  extends  Human{          public  $team = "bull" ;          public  $playerNumber = "23" ;          private  $age = "38" ;            // 静态属性定义时在访问控制关键字后面添加static关键字          public  static  $president  "David Stern" ;            // 静态方法定义          public  static  function  changePresident( $newPrsdt ){              // 在类定义中使用静态成员的时候,用self或者static关键字后面跟着::操作符,即可。注意,在访问静态成员的时候,::后面需要跟$符号              self:: $president = $newPrsdt ;              // 使用parent关键字就能够访问父类的静态成员              echo  parent:: $sValue ;          }      // 默认构造函数,在对象被实例化的时候自动调用      function  __construct( $name , $height , $weight , $team , $playerNumber ){          $this ->name = $name ; //$this是php里面的伪变量,表示对象自身。可以通过$this->的方式访问对象的属性和方法          $this ->height= $height //父类中的属性,可以通过$this来访问          $this ->weight= $weight ;          $this ->team= $team ;          $this ->playerNumber= $playerNumber ;      }      function  getAge(){          echo  $this ->name. "'s age is " . $this ->age. "<br>" ;      }        }      //类到对象的实例化      // 类的实例化为对象使用关键字new,new之后紧跟类的名称和一对括号      $jordan = new  NbaPlayer( "jordan" , "198cm" , "98kg" , "bull" , "23" );        $james = new  NbaPlayer( "james" , "210cm" , "98kg" , "heat" , "23" );            // $james->changePresident();这样会出错!      // 在类定义外部访问静态属性,我们可以用类名加::操作符的方法来访问类的静态成员。      echo  NbaPlayer:: $president . "<br>" ;      NbaPlayer::changePresident( "Dam silver" ); //替换静态变量      echo  NbaPlayer:: $president . "<br>" ; //可以输出替换的变量      echo  Human:: $sValue . "<br>" ;   ?>

  4.面向对象--final成员
    使用类的final成员特性就可以达到这样的效果
    -final关键字
    final使用后就不能继承类或方法,并且方法不能在子类中被修改

实例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?php //子类中编写跟父类方法名完全一致的方法可以完成对父类方法的重写(overwrite) // 对于不想被任何类继承的类可以在class之前添加final关键字 // 对于不想被子类重写(修改)的方法,可以在方法定义的前面添加final关键字 // 如果在baseclass前面添加final 那么这个类不能被继承 class  BaseClass{ public  function  test(){ echo  "BaseClass::test <br>" ; } // 添加final关键字能够让这个方法不能够在子类中重写 final  public  function  test1(){ echo  "BaseClass::test1 <br>" ; }   } class  ChildClass  extends  BaseClass{ public  function  test( $temp =null){ echo  "ChildClass::test " . $temp . "<br>" ; }   /*  父类中的final给了test1()方法,而不能继承 public function test1(){ echo "ChildClass::test1 <br>"; }   */   }   $obj  new  ChildClass(); $obj ->test( "TMP" ); $obj ->test1();  //可以继承父类中的test1()方法,但是不能改写 ?>

  

  5.面向对象--数据访问

实例:

  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 实例: <?php // 1.parent关键字可以用于调用父类中被子类重写了的方法 // 2.self关键字可以用于访问类自身的成员方法,也可以用于访问自身的静态成员和类常量; //不能用于访问类自身的属性;使用常量的时候不需要在常量名称前面添加$符号 //3.static关键字用于访问类自身定义的静态成员,防伪静态属性时需要在属性前面添加$符号      class  BaseClass{          public  function  test(){              echo  "BaseClass::test <br>" ;          }          final  public  function  test1(){              echo  "BaseClass::test1 <br>" ;          }        }      class  ChildClass  extends  BaseClass{          // const为常量,不需要用$在前面          private  static  $sValue  'static value' //这种叫伪静态          const  CONST_VALUE =  'A constant value' ;          public  function  test( $temp =null){              echo  "ChildClass::test " . $temp . "<br>" ;              parent::test(); //用parent关键字可以访问父类中被子类重写的方法  调用父类原来的test方法              self::called(); //可以用self调用自己这个类内的方法              echo  self::CONST_VALUE. "<BR>" ;              echo  self:: $sValue . "<BR>" ;          }          final  public  function  called(){              echo  "ChildClass::called() called <br>" ;          }      }        $obj  new  ChildClass();      $obj ->test( "TMP" );      // $obj->test1(); ?>

  

  6.面向对象--接口

问题:
  -人会吃饭,动物也会吃饭
  -有些植物也可以吃东西(比如猪笼草)

  ·接口就是把不同类的共同行为进行了定义,然后在不同的类里面实现不同的功能

  ·一旦某个类实现了某个接口,那么就必须实现接口定义的方法
  ·人这个类实现了“会吃东西”这个接口,那么人必须实现接口定义的“吃饭”方法


  ·某个类实现(implements)了某个接口和继承(extends)了某个类的区别
  -实现接口跟继承类很类似,但是接口不能直接创建自己的对象
  ·如果创建了“会吃东西”这个接口的对象,那么具体怎么吃根本不知道
  -继承的父类必须有该方法的具体实现,子类可以重写父类的方法,也可以不重写
  -接口里面的方法是不需要具体实现的,只要定义了方法的名称和参数就可以了,具体的实现必须在实现类中定义
  -一句话概括:类的方法必须有实现,接口的方法必须为空

实例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 <?php // interface关键字用于定义接口 interface  ICanEat{ // 接口里面的方法不需要有方法的实现 public  function  eat( $food ); }   // implements关键字用于表示类实现某个接口 class  Human  implements  ICanEat{ // 实现了某个接口之后,必须提供接口中定义的方法的具体实现 public  function  eat( $food ){ echo  "Human eating " . $food . "<br>" ; } } class  Animal  implements  ICanEat{ // 实现了某个接口之后,必须提供接口中定义的方法的具体实现 public  function  eat( $food ){ echo  "Animal eating " . $food . "<br>" ; } }   $obj  new  Human(); $obj ->eat( "Apple" ); $monkey  new  Animal(); $monkey ->eat( "Banana" );   // 不能实例化接口 // $eatObj = new ICanEat(); // 可以用instanceof关键字来判断某个对象是否实现了某个接口 var_dump( $obj  instanceof  ICanEat);   function  checkEat( $obj ){ if ( $obj  instanceof  ICanEat){ $obj ->eat( 'food' ); } else { echo  "The obj can't eat<br>" ; } } // 相同的一行代码,对于传入不同的接口的实现的对象的时候,表现是不同的,这就是多态 checkEat( $obj ); checkEat( $monkey );   // 可以用extends让接口继承接口 interface  ICanPee  extends  ICanEat{ public  function  pee(); }   class  Human1  implements  ICanPee{ public  function  pee(){ echo  "I can pee" ; } // 当继承一个接口的时候 也需要实现另一个接口中的方法 // 当类实现子接口时,父接口定义的方法也需要在这个类里面实现 public  function  eat( $food ){ echo  "Animal eating " . $food . "<br>" ; }   } ?>

  

  7.面向对象--多态
    因为接口的方法实现可以很多,所以对于接口里面定义的方法的具体实现是多种多样的,这种特性我们称为多态
    -比如接口A有两个实现B和C,B和C对A里面定义的方法的实现可以是不同的,这种现象就是多态。

实例:

1 2 3 4 5 6 7 8 9 10 11 12 13 <?php function  checkEat( $obj ){      if ( $obj  instanceof  ICanEat){          $obj ->eat( 'food' );      } else {          echo  "The obj can't eat<br>" ;      } } // 相同的一行代码,对于传入不同的接口的实现的对象的时候,表现是不同的,这就是多态 checkEat( $obj ); checkEat( $monkey );   ?>

  

  8.面向对象--抽象类
    ·接口里面的方法都是没有实现的,而类里面的方法都是有实现的。
    ·有没有一种形态,允许类里面一部分方法不实现呢?
    -当接口中的某些方法对于所有的实现类都是一样的实现方法,只有部分方法需要用到多态的特性
实例
-人和动物吃东西是不同的,但是呼吸是相同的,不需要为人和动物分别实现呼吸的功能。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 实例:(既有接口,里面又有类方法) <?php // abstract关键字用于定义抽象类      abstract  class  ACanEat{          // 在抽象方法前面添加abstract关键字可以标明这个方法是抽象方法,不需要具体实现          abstract  public  function  eat( $food );            // 抽象类中可以包含普通的方法,有方法的具体实现          public  function  breath(){              echo  "Breath use the air<br>" ;          }        }          // 继承抽象类的关键字是extends      class  Human  extends  ACanEat{          // 继承抽象类的子类需要实现抽象类中定义的抽象方法          public  function  eat( $food ){              echo  "Human eating" . $food . "<br>" ;          }      }      class  Animal  extends  ACanEat{          public  function  eat( $food ){              echo  "Animal eating" . $food . "<br>" ;          }      }        $man  new  Human();      $man ->eat( "Apple" );      $monkey = new  Animal();      $monkey ->eat( "banana" );      $monkey ->breath(); //和Animal类共用了抽象类中的breath方法 ?>

  

  五、面向对象的特殊实践
    1.面向对象--魔术方法
      ·__tostring()
      -当对象被当做String使用时,这个方法会被自动调用。
      -Echo $obj;

      ·__invoke()
      -当对象被当成方法调用时,这个方法会被自动调用
      -$obj(4);

实例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php      class  MagicTest{          // __tostring会在把对象转换为string的时候自动调用          public  function  __tostring(){              return  "this is tostring<br>" ;          }          // __inboke会在把对象当做一个方法调用的时候自动调用          public  function  __invoke( $x ){              echo   "this is invoke " . $x . "<br>" ;          }        }      $obj  new  MagicTest();      echo  $obj //自动调用__tostring();      $obj (5); //自动调用__invoke方法 ?>

  

  2.面向对象--魔术方法之 __call()和__callStatic()
    ·__call()
      -当对象访问不存在的方法名称时,__call()方法会被自动调用
    ·__callStatic()
      -当对象访问不存在的静态方法名称时,__callStatic()方法会被自动调用
    

    ·这两个方法在PHP里面也被称为方法的重载(overloading)
    -注意区分重写(overwrite)
    -通过这两个方法,同一个方法的名称的调用可以对应不同的方法实现

实例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php                class  MagicTest{              // 这个方法的参数第一个就是调用的方法的名称,第二个参数是方法调用的参数组成的数组              // implode 分割函数              public  function  __call( $name , $arguments ){                  echo   "Calling " . $name . " with parameters " .implode( "," , $arguments ). "<br>" ;              }              // 静态方法的重载,注意这个方法需要设定为static              public  static  function  __callStatic( $name , $arguments ){                  echo   "Static calling " . $name . " with parameters " .implode( "," , $arguments ). "<br>" ;              }      }      $obj  new  MagicTest();      $obj ->runTest( "para1" , "para2" );  //自动调用__call方法      MagicTest::runTest( "para1" , "para2" ); //自动调用__call方法   ?>  

  

   3.面向对象--魔术方法之 __get()和__set(),__isset(),__unset()
    -在给不可访问属性赋值时,__set()会被调用。
    -读取不可访问属性的值时,__get()会被调用。
    -当对不可访问属性调用isset()或empty()时,__isset()会被调用
    -当对不可访问属性调用unset()时,__unset()会被调用
    -所谓不可访问属性,实际上就是在调用某个属性时发现这个属性没有被定义,这时候不同的操纵会触发不同的魔术方法
    -这几个方法也被成为属性重载的魔术方法

实例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?php   class  MagicTest{      public  function  __get( $name ){          return  "Getting the property " . $name . "<br>" ;      }      public  function  __set( $name , $value ){          echo  "Setting the property " . $name . " to value " . $value . "<br>" ;      }      public  function  __isset( $name ){          echo  "__isset invoked<br>" ;          return  true;      }      public  function  __unset( $name ){          echo  "unsetting property" . $name . "<br>" ;      } }      $obj  new  MagicTest();      echo  $obj ->className. "<br>" ;      $obj ->className= "MagicClass" ;      echo  '$obj->className is set?' .isset( $obj ->className). "<br>" ;      echo  '$obj->className is empty?' . empty ( $obj ->className). "<br>" ;      unset( $obj ->className); ?>

 

    4.面向对象--魔术方法之 __clone()
      克隆方法(在没有设置对象的时候,会自动调用)

 


实例:(既有接口,里面又有类方法)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 实例: <?php      class  NbaPlayer{          public  $name ;          function  __clone(){              $this ->name =  "TBD" ;          }      }        $james  new  NbaPlayer();      $james ->name= "james" ;      $james2 = clone  $james ;      echo  "Before set up: James2's:" . $james2 ->name. "<br>" ;      $james2 ->name= "james2" ;      echo  $james ->name. "<br>" ;      echo  $james2 ->name. "<br>" ; ?>

  

总的全部就是这么多了,上面还没有说到封装特性。其实封装就是把一个物体抽象出来后作为一个个体进行属性,方法做成一个类,然后流出对应的入口和出口,就叫封装了。

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄