• javascript笔记


    day01
    am:
    前端三大基础知识:
    HTML:专门编写网页内容
    CSS:专门设计网页样式

    JavaScript:专门设计网页交互的语言
    交互:输入数据,程序处理数据,返回结果

    什么是JavaScript:
    1、专门设计网页交互的语言
    2、运行在JavaScript解释器中
    3、“解释”执行——像读书一样
    4、互联网第一大语言:JSer

    布兰登艾奇:4门语言拼凑出——JavaScript

    ECMAScript标准:JavaScript核心语法
    微软:JScript
    ECMAScript标准:一纸空文
    JavaScript和JScript都号称完全实现了ECMAScript标准
    W3C:DOM标准:专门操作HTML元素,CSS样式,事件的统一标准!

    BOM:专门操作浏览器窗口的工具。
    没标准,由浏览器厂商自行实现

    JavaScript=ECMAScript+DOM+BOM

    Mozilla基金会——>Firefox
    JSer最大挑战:浏览器兼容性问题

    JavaScript典型用途:
    1、客户端数据计算
    2、客户端表单验证
    3、动画

    JavaScript特点:纯文本;解释执行;弱类型;基于对象
    如何让使用:
    1、使用浏览器自带的js解释器:
    F12——>控制台
    光标处写脚本代码,回车执行。
    console:指代控制台:专门调式程序输出结果的窗口。
    log:控制台console提供的一个功能:向控制台输出一行日志。
    多行:shift+enter——>换行
    **JavaScript中区分大小写!**
    **字符串单双引号都行**
    2、单独安装专门的解释器软件:node.js Chrome V8
    win+R——>cmd——>node
    退出:两次Ctrl+c
    执行.js文件:1、先cd到.js文件所在路径
    2、node 文件名 回车
    3、随网页一同运行:
    浏览器 包含两种工具:
    排版引擎:专门加载HTML内容和CSS样式
    解释引擎:专门运行js脚本
    <script>元素:专门包含js脚本块的元素
    <script>中脚本块何时运行?随网页加载,解释执行
    <script>中都要使用js语法!
    html元素的事件“属性”中:
    什么是事件?元素可以根据鼠标或键盘的不同操作相应不同的交互行为。
    charset必须和文件的存储编码一致
    <script>解释执行,读到执行。先读先执行。——<script>放置的先后顺序影响程序结
    果。
    优化:放在body的最后

    一次定义处处使用,一次修改处处生效!
    解决:凡是重复编写的代码块,都要封装为一个方法
    方法:执行一个专门功能的一组代码的序列。
    一般定义在<head>下的<script>中
    语法:function 方法名(){重用的代码块}
    *不调不执行*

    调试:bug? debug:解决问题,排除错误
    只要没反应或效果没出来就是出错!——>F12
    查看错误原因——>定位错误位置!
    <script>脚本块中的错误,仅影响“当前脚本块”中出错“位置之后”的脚本执行。
    不影响<script>之外的其他元素加载或脚本执行。
    function中的错误:只有调用方法是才触发!

    页面内部脚本块问题:仅当前页面可用!
    解决:外部.js文件!
    什么是.js文件:专门保存js脚本源代码的文件。
    源代码都要放到js解释器才能执行。
    如何使用.js文件?2步:1、创建.js文件,编写源代码 2、在页面引入外部.js文件
    内外部同名方法,解释执行!

    pm:
    JavaScript=ECMAScript(核心语法)+DOM(操作网页内容)+BOM(操作浏览器
    窗口)

    ECMAScript(核心语法)
    *区分大小写*
    *字符串必须用引号(单双都行)包裹*
    *每条语句结尾都建议有分号*

    语句:让程序可以做一件事的一行命令
    脚本块:多行语句的序列
    程序:让计算机可以模拟执行人类的想法!
    注释:不会被解释执行或显示的代码说明——给程序员看的
    注释也占网页流量!生产环境必须去掉!
    HTML注释:<!---->
    CSS注释:/**/
    JS注释://单行注释 /*多行注释*/

    *变量*
    什么是变量?内存中专门存储数据的空间
    程序都是在内存中运行
    任何程序:IPO:Input Process Output
    数据 数据 数据
    何时使用变量?只要在程序中临时存储数据,都要放在变量中
    怎么使用变量?声明,命名,初始化和使用
    声明:在内存中开辟一个存储空间,并且起一个名字
    怎么声明?var 变量名;
    赋值:将等号右边的数据,装入等号左边的变量中!
    如果未赋值:js默认赋值为undefined

    命名规则:见名知意
    保留字、关键字不能当变量名
    保留字:js中已经占用的特殊意义的关键字
    使用:使用变量名等于直接使用变量中存储的数据
    +:拼接多段文字为一句话!

    常量:一旦创建,值不可改变的特殊变量
    如何使用常量:const 常量名=常量值;

    强调:只有等号可以向变量中存入新值。普通运算不会改变变量的值。只是使用变量的
    值。
    只要带var就是声明,只要声明就会开辟内存空间、
    js中新同名变量的空间会替换旧的空间。
    有几个var,就会创建几个存储空间。

    数据类型:变量中存储的数据类型。
    js是弱类型:变量本身没有类型。只有变量中的值才有类型。
    一个变量,可以反复保存不同类型的数据。
    为什么要有数据类型:现实中所有数据根据用途不同,都分为不同数据类型。

    原始类型:数据保存在变量本地!
    number类型:表示一切用于比较或数学计算的数字
    程序中数字分整数、浮点数(现实中的小数)
    js中一切数字都用number保存,不分整数类型和小数类型
    如何定义number类型?不带引号的数字字面量
    程序中数字类型的舍入误差:程序中不能准确表示1/10,就好像现实中不能准确表示
    1/3一样!
    如何修正:按指定位数四舍五入:数字.toFixed(小数位数)
    今后计算结果小数位数超长,说明碰到舍入误差。按位四舍五入。
    精度计算不要用JavaScript

    string类型:一串字符的序列!
    Unicode:对所有语言文字中的字符编号
    Why“因为计算机只处理数字,无法处理文字。
    计算机处理unicode编号,就等效于处理编号对应的文字。
    转义字符:专门表示非打印字符以及特殊符号
    如何使用转义字符:特殊符号 比如: 换行 、 tab键
    如果字符串中包含与语法相冲突的特殊字符,要用转为原文

    *字符串变量的内容一旦创建补课费改变!如果改变,只能创建新字符串,抛弃旧字符串
    。*
    鄙视题!
    var str = "Hello";
    str = str + “Word”;
    3个!

    boolean类型:仅有两个值的特殊数据类型:true,false
    何时使用boolean?只要一个值只有真假两种情况,就用boolean类型

    undefined类型:表示一个变量仅声明过,但从未赋值。所有未赋值的变量,默认值都
    是undefined。
    undefined类型的值还是undefined!

    原始类型的大小:
    number:整数4字节,浮点8字节
    string:每个字符两字节


    day02
    回顾:
    JavaScript:ECMAScript(核心语法)
    DOM(操作网页内容)
    BOM(操作浏览器窗口)
    ECMAScript:标准
    Netscapt:javaScript Microsoft:JScript

    变量:内存中存储数据的一块空间
    一切数据必须存在变量中
    声明:var 变量名——>在内存中开辟一块空间
    赋值:变量名=值——>将值保存到左边的变量空间中备用
    使用:使用变量名,就等效于直接使用变量中的数据

    数据类型:
    why:存储空间的大小,用途
    原始类型:数据保存在变量本地
    number string boolean undefined null

    string:字符串内容一旦创建不能改变
    var str = "Hello";
    str = str + "World";
    3个!

    正课:
    数据类型间的转换:
    隐式转换:程序自动转换数据类型(坑)
    弱类型:1、变量声明是不必限定数据类型,今后可能保存任何数据类型
    2、数据类型间可以自动类型转换
    仅考虑+:只要有字符串参与,一切类型都加""变为字符串
    如果没有字符串,都转换为数字计算:其中true——>1 false——>0

    强制转换:程序员通过调用专门函数,手动转换类型
    2 string:x.toString();——>将x转为字符串类型
    2 number:Number(x);——>将任意类型转为number类型
    string——>number:
    转为整数:var num = parseInt("str");
    读取字符串中的整数部分
    1、从第一个字符向后读。
    2、如果碰到第一个数字字符,开始获取数字,再次碰到不是数字的字符,停
    止读取
    3、如果开头碰到空格,忽略
    4、如果碰到的第一个非空格字符,不是数字,说明不能转——>NaN: Not
    a Number
    什么是NaN:不是数字(内容)的数字(类型)
    转为浮点数:var num = parseFloat("str");
    用法和parseInt全完相同
    唯一差别:parseFloat认识小数点

    prompt("提示信息"):专门用于请求用户输入数据,收集数据的对话框!
    var str = prompt("提示信息");
    *凡是从页面上获得的数据,都是字符串!必须先转换再计算*

    什么是运算符:程序模拟人类运算的特殊符号
    算数运算:-任意类型做-,都会被转为数据类型
    如果有参数,不能自动转换为数字,则返回NaN
    如果除数为0:Infinity——>无穷大
    typeof(x):判断任意数据的类型
    被除数%除数——模运算:被除数/除数,取除不尽的余数
    何时用:限制一个数不能超过某个最大范围时

    递增/递减运算:i++ ==> i = i +1;
    i++单独用:++放前放后,效果一样:i++ ==> ++i;
    i++出现在表达式内部:
    前++,前+1,再参与表达式
    后++,先用旧值参与表达式。表达式之后再+1

    关系运算:判断大小!条件判断中使用
    结果:成立:true,不成立:false
    *自带隐式类型转换*
    字符串参与运算:从第一个字符开始,取出每个字符 PK unicode编号
    "Hello" H e(101)
    "Hi" H i(105)
    关系运算中:任何类型和数字比较,都转为数字,再比较
    布尔类型参与关系运算,始终转为数字比较

    PM:
    关系运算:现将参与判断的数据,强转为相同类型,再比较
    字符串比较:
    undefined做==比较:
    undefined类型,从null类型继承来的
    undefined值被自动转换为null!
    undefined == null ——>true
    ===严格相等:不带自动类型转换的相等比较!
    类型和值必须都相等!才返回true。
    严格相等最初就是为undefined和null设计的
    只要不确定比较的类型,又不希望自动类型转换时,就用===

    NaN做==:
    isNaN(x):专门用来判断一个数据是不是NaN
    如果是NaN返回true;如果不是NaN返回false

    只要不能转换为数字的,都返回true
    只要能自动转换为数字的,都返回false
    关系运算中"",可以自动转换为false或0
    总结:1、普通数据,先转换为相同类型,再比较
    2、undefined,就用===
    3、NaN,就用isNaN(x)

    逻辑运算:基于多组关系运算,得出一个结论
    &&:而且
    ||:或者
    !:非,颠倒true和false,今后只要颠倒判断结果,就用!

    短路逻辑:只要前一个判断足以得出最终结论,则后续条件不执行!

    验证是不是汉字:>="u4E00" && <="u9FA5"
    闰年的判断公式:(year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)

    位移:n << m ——>n*(2的m次方)
    n >> m ——>n/(2的m次方)

    赋值运算:赋值运算结果就是等号右边表达式的结果
    扩展的赋值表达式:对已有的数据计算的同时,将结果再存回变量
    何时使用:修改原变量值

    三目运算:根据不同条件,动态返回不同结果!
    三目:至少需要3个表达式。
    语法:
    一个条件,二选一:条件?当条件满足时返回的值:当条件不满足时返回的值
    多个条件,多选一:
    条件1?条件1满足时的值:
    条件2?条件2满足时的值:
    条件n?条件n满足时的值:
    默认值;
    需求1:2个数中取最大的
    var score1 = 100;
    var score2 = 80;
    var result = score1 > score2 ? score1 : score2;
    注意:后一个条件中不用包含否定前一个条件的关系判断。
    因为,进入后一个条件隐含的条件就是前一个条件不满足。


    day03
    NaN == NaN? false NaN和任何数据比较,永远返回false
    今后只要可能判断NaN时,用isNaN(x)
    var str = "Hello";
    str > 10? str > 10000? false
    NaN NaN
    关系运算中,字符串比数字,字符串转为数字!

    注意:逻辑运算中,不要急于将第一个条件之后的++/--提取出来

    使用变量错误的情况:*没声明的变量,只要使用就出错!*
    var name;
    console.log(Name);//程序运行错误错误!会导致程序停止
    console.log(name);//undefined1

    函数(方法):封装执行一项专门任务的步骤的代码序列
    何时定义方法?只要发现一段代码重复使用,就封装为方法
    语法:声明
    function 方法名(参数列表){
    方法体:步骤清单
    return 返回值;
    }
    调用:方法名(参数值列表);
    参数:方法内独有的变量。接收传入数据,在方法内处理。参数让方法变灵活!
    如何声明方法参数:不用var!
    参数何时被创建?只有方法被调用时才自动创建
    返回值:方法执行完成后,由方法返回的数据
    定义返回值:不用再声明变量,直接用return值!
    为什么定义返回值:因为调用方法的人需要明确的返回结果。
    返回值主要给调用者使用。
    return:本意退出方法!
    退出同时,可返回数据!
    可以再任何需要的地方,调用方法执行返回值;
    带返回值的方法,使用时,等效于直接使用返回值数据。

    作用域:一个变量的可用范围!
    全局作用域:直接放在全局作用域中的变量,叫全局变量
    只要希望所有作用域公用的变量都要声明在全局作用域
    window
    局部(函数)作用域:声明在方法内部的变量或方法参数的变量都叫局部变量
    值传递:将一个变量的值赋值给另一个变量,其实将原变量中的值,复制一份给新变量

    js中一切赋值都是值传递!

    对未声明的变量赋值:js会自动在全局创建该变量!

    函数作用域和变量作用域完全一样
    函数作用域在调用方法时创建,方法执行完立刻销毁!

    PM
    问题:
    方法参数:依据方法内部的处理逻辑至少需要几个数据才能正常执行。
    方法参数和外部定义了了那些变量没有任何关系。
    方法参数作用:1、接收外部传入数据,在方法内处理
    2、规定调用方法的人必须提供哪些参数!

    方法的返回值:根据方法调用者的需要! 如果方法调用者需要明确返回一个结果,就定
    义返回值!否则,可以不定义返回值!
    何时必须使用变量接住?方法的返回值,后续程序可能反复使用!

    鄙视题:
    var num = 0;
    function f1(num){
    var num = 100;
    console.log(num);
    }
    f1();
    console.log(num);
    //100 0

    正课:
    自定义函数:
    全局函数:ECMAScript定义了标准,由个浏览器厂商已经实现的函数。我们直接调用

    isNaN(x) parseInt/Float(x)

    encodeURI( kword ):将url中的非法字符转为单字节符号——编码
    decodeURI( kword ):将encodeURI转后的字符串,转换为原文——解码
    unicode编码:每个字符2字节
    utf-8:字母、数字单字节,汉字3字节

    url规定参数值中,再次出现保留字,就是非法:
    保留字:/ ? $ : 等

    encodeURIComponent( kword );既能对多字节非法字符编码,又能对单字节非法字符
    编码——今后只使用component就够了
    何时使用?将数据通过url发送时,都要先编码再发送
    decodeURIComponent( kword );对encodeURIComponent()编码的字符串解码。收
    到编码后的字符串后,都要先解码,再处理。

    eval():专门执行字符串格式代码

    程序结构:3种:顺序;分支;循环

    程序:IPO
    需求:找名词——>程序中的数据
    两类:输入数据
    输出数据
    分析处理流程:

    分支结构:程序运行过程中,可以根据不同的条件,执行不同的任务。
    分支结构:if...结构:1件事,要么做,要么不做
    if...else...结构:2件事,二选一执行
    else if结构:多件事,多选一执行



    day04
    回顾:
    方法参数:方法内处理逻辑必须的数据
    参数仅限方法内部使用!方法外无法访问方法的参数变量
    参数名称自定义!
    返回值:调用者是否需要获得方法的执行结果

    分支:if结构 1件事 可做可不做
    if...else... 2件事 必须二选一
    if...else if...[else...] 多件事 多选一执行

    正课:
    switch...case...多条分支,根据条件判断,选择执行
    switch...case...用的是严格相等,不带自动类型转换
    语法:swith(表达式){
    case 表达式1://如果表达式的值===表达式1的值
    代码段1;
    case 表达式n:
    代码段n;
    default://如果表达式的值和都有的case都不相等
    默认代码段;
    }
    运行机制:如果找到与表达式匹配的case,不但执行当前case下的代码,而且之后所有
    代码都被触发!
    switch(true){
    case socre >= 90: console.log("A");
    case score >= 80: console.log("B");
    case score >= 60: console.log("C");
    default: console.log("D");
    }
    break:退出当前结构;
    多条件公用同一套执行逻辑是,不加break。
    switch(true){
    case socre >= 90: console.log("A");break;
    case score >= 80: console.log("B");break;
    case score >= 60: console.log("C");break;
    default: console.log("D");
    }

    循环结构:程序反复执行同一套代码段。遇到结束条件,会结束执行。
    没有循环结束条件,永远循环呢执行——死循环

    循环三要输:
    1、循环条件:循环继续执行的条件。一旦循环条件不满足,循环立刻退出!
    2、循环变量:用于循环条件中做判断的变量。循环变量都会向着循环退出的趋势变化
    (不满足循环条件的趋势)——循环计数器
    3、循环体:每次循环要做的事情

    while循环:当满足条件时,就继续循环做...事
    语法:
    var 循环变量;
    while(循环条件){
    循环体;
    迭代变化循环变量;
    }
    break:退出当前结构
    while中何时用break:循环条件不满足之前,希望强行退出循环。
    如何使用break?可以放在任何需要退出循环的位置。

    随机数:Math.random();0<=n<1
    任意min——max之间取随机数
    公式:parseInt(Math.random()*(max-min-1)+min)

    do-while循环:先执行一次循环体,再判断是否继续!
    如果循环条件不满足,循环体至少可以执行一次!
    var 循环变量;
    do{
    循环体;
    迭代变化循环变量;
    }while(循环条件);

    *变量声明提前*:“相同作用域内”,var...不论出现在什么位置,解析时,优先提取到
    js开始位置“声明”!

    for:完全等效于while循环。
    循环变量变化规律固定,循环次数已知、固定
    for(声明并初始化循环变量;循环条件;迭代变化循环变量){
    循环体
    }

    continue:跳过本轮循环,继续执行下一轮循环

    遇到复杂问题:
    先用简单办法做最简单的事情。
    从简单办法中找规律!

    day05
    程序 = 数据结构 + 算法
    良好的数据结构,可以极大提高程序的执行效率!

    数组:存储:连续存储多个数据的存储空间
    使用:相当于多个变量的集合
    why?现实中数据都是批量分类管理
    何时使用:只要批量管理多个数据,就要用数组保存
    如何使用:创建,初始化,访问数组中的数据
    创建:数组都是用[]创建出来的。
    var arr = [];——>创建了一个数组对象,数组中包含0个元素
    var arr = [90, 34, 23];——>创建了一个数组对象,数组中连续存储3个元素
    2个不限制:1、不限制元素的个数! 2、不限制元素数据类型

    *数组是引用类型的对象*
    原始类型:数据保存在变量本地
    引用类型:数据不保存在变量本地!保存在“堆”中。
    由地址指向实际数据
    引用类型特点:可以保存多个数据,而且数据个数随时变化
    why?原始类型中只能保存1个值
    1个值无法精确描述一个东西
    现实中,都是用多个属性共同描述一样东西
    对象:凡是存储在堆中的,都是对象!
    使用引用类型的对象:使用变量,等效使用对象的地址
    使用对象地址,等效于使用对象本身
    数组对象支持直接输出数组内容

    其他数组创建语法:var arr = new Array(num);
    new:要在堆中开辟空间!
    Array:ECMAScript标准的内置类型
    new Array:在堆中创建一个数组类型的存储区域
    (num):初始创建num个元素
    var arr = new Array(7);
    //[undefined, undefined, undefined, undefined, undefined, undefined, undefined]
    undefined输出时,变为一个空字符
    var arr = new Array(元素1, 元素2,..., 元素n);

    null:一个变量没有指向任何对象
    何时使用null:主动释放对象!主动释放的对象不能被找回
    null vs undefined:
    null专用于主动释放对象!
    undefined:专用于自动初始化任何未赋值的变量

    垃圾回收:js引擎自动销毁不再被引用的对象!
    垃圾回收程序:随js程序运行而后台同时运行
    只要对象还有变量引用,就不回收。

    访问数组:数组一组变量的集合。
    如何获得其中一个变量/数据:下标,数组中唯一标识一个元素的序号。从0开始。最后
    一个元素的下标是“元素个数-1”

    js内置对象不但封装存储,而且封装常用API
    API:已经实现的方法!可以直接调用!
    Array API:
    1、arr.length属性:数组中元素的个数
    访问任意数组的最后一个元素:arr[arr.length - 1]
    length属性值,随数组长度变化而自动变化!
    js中数组可根据程序需要,“自动扩容”,保证程序正常执行

    数组扩容和缩容:都是设置length属性的值
    如果length属性值>旧值,会扩容;反之,缩容(截断)
    被截断的元素,不能被找到,不会被回收。只能随数组对象一起回收。
    固定用法:在任意数组结尾追加一个新元素:arr[arr.length] = 新值;

    下午:
    栈中的变量 生命周期:和堆完全不同
    var a = 5;//全局变量随网页生命周期
    function fun(){
    var b = 10;
    }
    fun();//作用域环境栈
    /*fun的作用域环境栈 出栈 fun中局部变量,一同消失*/
    console.log(b);//refError
    结论:局部变量的声明周期和所在方法的作用域环境栈有关
    作用域创建,局部变量一同创建
    作用域结束,局部变量一同消失

    什么是数组遍历:对数组中每个元素执行相同的操作
    for(var i = 0; i < arr.length; i++){
    arr[i]——>当前元素
    }

    关联数组:数组下标可以自定义名称!Key/value对
    何时使用关联数组:数组元素的内容无法描述自己的意义时,使用关联数组为每个元素
    起名
    关联数组的length属性作废了!
    for in:专门遍历关联数组用的!
    for(var key in arr){
    //从第一个元素开始,将元素的key赋值给临时变量key
    arr[key]——>当前正在遍历的元素的值(value)
    }
    关联数组直接量定义方式:强调:大括号
    {"key1":"value1", "key2":"value2", ...}

    冒泡排序:[3, 5, 3,。。]:见array.html

    数组常用方法:
    x.toString()方法:任何对象都有toString方法
    默认用,分割每个元素
    将任何对象转为字符串
    一般不主动调用,js在需要时自动调用
    x.valueOf()方法:同toStrin()

    var str = arr.join("分隔符"):将数组转为字符串。但是可自定义分隔符!
    用法,将字符拼接为单词或句子 chars.join("");

    var newArr = arr.concat(1个元素值, [数组], ...):将参数拆散成单个元素,追加到数组
    中。
    *不会修改原数组,只能返回新数组对象*

    var subArr = arr.slice(start, end + 1);截取数组下标从start开始,到end位置的元素,
    生成子数组对象。*含头不含尾*

    arr.splice:删除!插入!替换!
    删除元素:arr.splice(start, count);
    替换元素:arr.splice(start, count, 值1, 值2, ...);
    插入元素:arr.splice(start, 0, 值1, 值2, ...)
    返回每次删除元素组成的新数组

    arr.reverse();颠倒所有数组元素
    arr.sort();默认升序排序。默认都转为字符串排序!

    day06
    手册:JavaScript——>js对象——>js数组——>Array对象参考手册
    回顾:
    转为字符串:x.toString()——>任何对象都有toString方法
    var str = arr.join("分隔符")——>自定义元素分隔符
    固定用法:arr.join("");——>将数组中的字符串无缝拼接为单词或字符串

    拼接和截取:var newArr = arr.concat(otherArr, 值1, ...)
    var subArr = arr.slice(start, end + 1);
    复制原始数组中的部分元素,原数组不变
    含头不含尾

    splice:*直接修改原数组!*返回被删除 的元素
    删除:[var removed =] arr.splice(start, count);
    替换:[var rrmoved =] arr.splice(start, count, 值1, 值2, ...);
    自动调整数组容量,容纳所有修改的新值
    插入:[var rrmoved =] arr.splice(start, 0, 值1, 值2, ...);

    正课:
    排序:arr.sort();默认按字符串升序排列
    自定义排序:2步:Step1:定义比较器函数!
    什么是比较器函数?定义任意两值比较策略的方法
    比如:num1 - num2 > 0 ——> num1 > num2
    num1 - num2 < 0 ——> num1 < num2
    function compare(a, b){
    return a - b;
    }//如果返回>0数,a > b; 如果返回<0数,a < b; 如果返回=0数,a = b;

    Step2:将比较器函数传递给sort方法!
    ***如何将方法做参数传递?***
    js中方法也是一个对象!方法名就是指向对象的变量名!
    function compare(a, b){return a - b;}
    //可以定义在使用前后的任何位置
    //原因:var声明和function声明自动提前!
    相当于:var compare = new Function("a", "b", "return a - b;");
    //必须定义在使用之前!原因:仅声明提前,赋值不能提前!
    arr.sort(compare);注意!将方法作为对象传递是,仅使用方法名,后不加圆
    括号。

    降序:颠倒比较结果,可以导致升序变降序
    升序:function compareASC(a, b){return a - b;}
    颠倒(*-1):function compareDESC(a, b){return b -a;}

    栈和队列:
    什么是栈?后进先出!(LIFO)栈其实就是数组,只不过用一对方法模拟了栈的操作!
    栈:只能从数组一端出栈,入栈。另外一端封闭!
    操作栈:
    结尾入栈出栈:元素下标始终不变,最后一个元素始终最新
    入栈:arr.push(值1, ...);
    出栈:var last = arr.pop();
    开头入栈出栈:所有元素下标随入栈出栈操作而变化
    入栈:arr.unshift(值1, ...);
    出栈:var first = arr.shift();
    队列:FIFFO
    入队列:arr.push(值1, ...);
    出队列:var first = arr.shift();

    二位数组:数组的元素又是另一个数组对象!
    创建二位数组:创建普通数组,完全一样!
    只不过将普通元素,换为一个数组对象而已
    var arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
    arr[3] = [10, 11, 12];
    如何访问二位数组中的任意元素:arr[父数组中的下标][子数组中的下标]
    何时使用二位数组:数据包含明显上下级关系

    内置对象
    什么是内置对象?内置对象就是ECMAScript标准中已经定义好的,由浏览器厂商已经
    实现的标准对象!
    内置对象中封装了专门的数据和操作数据常用的API。
    JavaScript中内置对象:
    String,Boolean,Number,Array,Date,Math,Error,Function,Object,Global

    包装类型
    什么是包装类型?专门封装原始类型的数据,并提供对数据常用操作的内置类型。
    为什么要用包装类型?让原始类型的数据也可以像引用类型一样,拥有方法和属性。
    JavaScript中的包装类型有三个:
    String类型,Number类型,Boolean类型
    何时使用包装类型?只要用原始类型的数据调用方法或访问属性,js引擎都会自动创建
    对应的包装类型对象。
    方法调用完,包装类型对象自动释放。
    var str = "Hello";
    //var strObject = new String(str);
    str += "world";
    //strObject = null;

    String包装类型:*字符串内容,一旦创建,不可改变*
    创建原始类型字符串变量:
    直接量:var stuName = "Smith";
    类型转换:var priceString = String(190.3);
    创建引用类型字符串对象:
    var carType = new String("BMW528Li");

    str.length:返回str字符串中的字符个数
    大小写转换:都转小写:str = str.toLowerCase();
    都转大写:str = str.toUpperCase();
    何时使用:希望大小写一视同仁时,就要先转换,在处理

    day07
    内置对象:见PPT
    包装类型:见PPT
    var num = 5.678;//原始类型
    //num = new Number(num);//包装类型
    console.log(num.toFixed(2));
    //num = null;//释放包装类型对象!

    创建字符串:原始类型还是包装类型?是否new
    var str = "...";//原始类型
    var str = String("...");//原始类型,类型转换
    **********************************************
    var strObj = new String("...");//包装类型对象

    转义字符:代替字符串中的非打印字符:
    如果字符串内容中包含和语法冲突的特殊字符,可用转为普通字符
    比如:console.log(" js是互联网"第一大语言"");

    字符串内容一旦创建不能改变!
    如果修改,都要创建新字符串,保存新结果,替换旧字符串
    var str = "Hello";
    var strObj = new String(str);
    str = str.toUpperCase();
    //strObj = null;
    console.log(str);
    *规律:所有字符串API,都需要变量接收返回值!*

    字符串的字符个数:str.length属性
    *字符串类型底层其实都是用字符数组实现的*
    比如:str[i]

    大小写转换:大小写字母一视同仁时,先转化,再处理
    比如:重名验证,重复邮箱,验证码

    获取指定位置的字符:var char = str.charAt(index);

    获取指定位置字符的unicode编码:var num = str.charCodeAt(index);

    优化:*频繁对字符串+=,要用数组代替!不会产生中间对象*
    Step1:每个字符串放入数组
    Step2:join("")拼接字符元素

    今天后要把任何类型变为String,不要用toString,而用+"",效率更高。

    字符串三大操作:1.查找关键字! 2.替换关键字 3.获取子字符串
    查找关键字:var index = str.indexOf("关键字");
    返回关键字所在位置!*如果没找到,返回-1!*
    indexOf:懒:只找第一个关键字位置!
    蠢:默认只能从位置0开始!
    var index = str.indexOf("关键字", from);
    from:开始查找的位置,从from开始向后查找
    一句话办几件事时,可以把表达式当值用!
    var str = "女神说要来,我草草的收拾了房间。结果她又说不来了。我说:我草";
    var index = -1;
    while((index = str.indexOf("我草", index + 1)) != -1){
    console.log("位置" + index + "发现关键字");
    }

    从最后一个字符,向前找:只要关键字离结尾近,就用last
    var index = str.lastIndexOf("关键字", from);
    from:开始查找的位置,从from开始向前查找
    *返回的index完全相同!字符在数组中的下标是固定的!*
    2处修改:index从str.length开始;每次index要-1

    2.获取子字符串:以下三个方法省略第二个参数,默认都是取到结尾!
    var subStr = str.slice(start, end + 1);
    start,end支持正负
    var subStr = str.substring(start, end + 1);
    用法同slice!唯一差别:不支持负值作为参数!
    var subStr = str.substr(start, *count*);
    JavaScript——>js字符串——>

    下午:
    按规律分割字符串:var subs = str.split("分隔符"[, count]);

    鄙视题:var str = "no zuo no die";

    课堂练习:判断字符的种类:unicode范围:
    48-57:0-9 数字字符
    65-90:A-Z 大写字母
    97-122: a-z 小写字母
    19968-40869:汉字

    什么是模式匹配:可以设置查找或替换的规则!
    何时使用模式匹配:要查找的关键字可能发生有规律的变化。
    如何使用模式匹配:1.先定义模式:/关键字/模式
    比如:var reg = /no/ig; no是要查找的关键字原文,不加""
    i表示忽略大小写! g表示全局查找和替换!

    String类型中,提供了专门支持模式匹配的API!
    按模式*替换*关键字:str = str.replace(reg, "新值");
    默认replace仅替换第一个关键字!
    要想全局替换,要在模式中定义“g”

    获得*所有*关键字的*内容:var kwords = str.match(reg);
    只能取得关键字的内容,无法确定每个关键字的位置!
    kwords.length:找到的关键字个数!
    *如果未找到,返回null!*
    只要有可能返回null!都要先判断 !=null,再处理!

    SetupRegexBuddy.exe 全部默认安装

    var index = str.search(reg); 和indexOf完全相同!
    indexOf不支持模式查找!search其实是indexOf的模式查找版

    今后在网页中只要处理字符串的格式,就要用正则表达式
    *正则表达式*
    什么是正则达表示:字符串中字符出现的规律
    何时使用正则表达式?验证字符串格式,查找关键字,替换关键字
    比如:银行卡查询密码:6位数字
    用户名:字母,数字,_的组合

    正则表达式:
    选择符号:[所有备选字符]:[去草],必须多选一使用
    一个[],只能代表一位字符的规则
    [^xxxx]:表示出了xxxx都行!反义。注意必须放在[]中的第一个位置,否则变为普通字
    符匹配。

    -符号:字符的范围:备选字符是连续的范围!
    比如:[0-9] [a-z] [A-Z] [a-zA-Z]//-可以局部使用
    汉字范围:[u4e00-u9fa5]

    预定义字符集:使用简化的符号,定义常用字符集
    比如:[0-9] ——> d [a-zA-Z0-9_] ——> w 空字符 ——> s

    如果规则正文中出现特殊符号,用转为原文

    .一个人一字符!

    数量词:规定前边一个字符出现次数的两次
    语法:{min,max}
    {num}:固定长度
    {min,}:至少min个,多了不限
    手机号:+86s1[3578]d{9}
    用户名:w{6,8}

    day08
    回复:
    []:备选字符集,只能多选一。一个[]只能匹配一位字符
    比如:我[去草]:我去 我草
    []内:开头^:除了xx都行:[01235689] ——> [^47]
    -:表示备选字符的范围 :[a-z] [0-9] [A-Z]

    预定义字符集:
    [0-9] ——> d
    [a-zA-Z_] ——> w
    s:空字符: 空格

    量词:修饰前一位字符出现的次数
    {min,max}:最少min个,最多max个
    {min,}:最少min个,最多不限制
    {num}:固定num个

    比如:验证座机号码:d{3,4}-d{7,8}

    正课:
    特殊数量词:+ * ?
    ?:可有可无,对多只能出现一次
    比如:我了?去: 我去 我了去 我了个去X 我了了去X

    *:可有可无,不限制出现次数
    比如:点亮我生命的火*:
    点亮我生命的
    点亮我生命的火
    点亮我生命的火火火

    +:至少出现一次!不限制出现次数
    比如:点亮我生命的火+:
    点亮我生命的火
    点亮我生命的火火火

    如果正文中出现+?*,都要用转义

    ():分组:改变模式的匹配顺序
    比如:验证身份证号:d{15}(d{2}[0-9xX])?
    验证手机号:(+86)?s+1[3578]d{9}

    ^:整个正则表达式的开头,表示以xxx开始
    $:整个正则表达式的结尾,表示以xxx结束

    ?= 预判,前一个字符之后,必须紧跟xxx
    ?! 预判,前一个字符之后,必须不能跟xxx

    课堂练习:中文姓名:[u4e00-u9fa5]{2,6}
    电子邮件:w+@w+([-]w+)*(.w+)+
    其中:w+([-]w+)* —— 匹配域名
    一个以上的字母,后可跟“-字母”,可有可无
    (.w+)+
    “.字母”组合至少出现1次

    RegExp对象:专门封装一条正则表达式,提供使用正则表达式的常用API
    如何使用RegExp对象:1.创建 2.调用API
    v如何创建正则表达式对象:ar regExp = /正则表达式/ig;
    API:
    验证:var boolean = regExp.test("被检查的字符串");
    如果验证通过:返回true;否则返回false
    验证 vs 查找:
    验证要求完整匹配!查找要求部分匹配!

    **test方法默认:只要找到就返回true!**
    正则表达式前加^,后加$

    查找:exec:查找关键字的位置,又能找到关键字的内容
    indexOf不支持正则,search支持正则,每次只能找1个
    match所有内容,但得不到位置!
    var arr = regExp.exec("被查找的内容");
    arr[0]:找到的关键字内容
    arr.index属性:找到的关键字的位置
    exec方法每次只能找1个,但是每次自动修改regExp对象的lastIndex属性!
    regExp对象的lastIndex属性:表示下次开始匹配的位置!

    查找:仅判断有没有,或者仅查找位置:str.indexOf()
    支持正则表达式:str.search()
    仅所有关键字的内容:str.match()
    即找位置,又找内容:regExp.exec()

    /正则表达式/
    var regExp = new RegExp("\d{6}", "ig"); 动态创建正则表达式
    强调:所有都要改为\

    贪婪模式: .+ .*,默认先匹配整个字符串,再缩小范围!
    懒惰模式: (.+?) (.*?),从第一个字符开始,向后扩展范围

    下午:
    从正则表达式匹配的内容中,取一部分:RegExp.$n
    n:正则表达式中第n个分组,其实就是第n个圆括号
    强调:分组从1开始
    必须通过RegExp类型,直接调用$n,不能使用对象!

    String对象与正则表达式
    str = str.replace(/正则表达式/ig, "替换值");
    var arr = str.match(/正则表达式/ig); str.search()
    str.split(/正则表达式/);

    trim功能:去除字符串开始和结尾的空格。中间空格不去除!
    对输入字符串的处理,多数要先清除开头结尾空格,再处理
    IE8不支持trim()方法!
    自定义trim()方法:
    function trim(str){
    var regExp = /(^s+)(s+$)/g;
    str = str.replace(regExp, "");
    return str;
    }

    String总结:所有的API都无法修改原字符串,都会返回新的字符串
    所有StringAPI都需要用变量保存结果!
    str.length 字符个数
    str = str.toUpperCase()/toLowerCase()
    查找关键字:var index = str.indexOf("关键字"[, from])
    var arr = str.match(/正则表达式/g);
    获得子字符串:var substr = str.slice(start, end + 1);
    str.substring(start, end + 1);
    str.substr(start, count);
    替换:str = str.replace(/正则表达式/g, "替换值");
    获得指定位置的字符:var char = str.charAt(index);
    str[index];
    字符编码转码:var code = str.charCodeAt(index);
    var char = String.fromCharCode(code);

    RegExp对象总结:
    var reg = /正则表达式/ig;
    var reg = new RegExp("正则表达式", "ig");
    *其中所有的都要改为\!*

    验证str中时候包含reg匹配的关键字:
    var boolean = reg.test(str);
    *强调:完整验证,都需要在正则表达式前加^后加$*

    同时查询所有关键字的内容和位置
    while((arr= reg.exec(str)) != null){
    arr[0] ——> 找到的一个关键
    arr.index ——> 当前关键字的位置
    }

    RegExp.$n:
    获得正则表达式中第n个分组(圆括号)匹配的子字符串

    Math类型:封装了所有数学计算有关的API
    不能new!
    Math.PI

    Math.round(num) ——> 四合五入取整
    Math.ceil(num) ——> 向上取整
    Math.floor(num) ——> 向下取整

    Math.pow(底数, 幂);
    Math.sqrt(num);//平方根!

    绝对值:Math.abs(num);

    Math.max/min(值1, 值2, 值3, ...);
    取数组中的最大值:var max = Math.max.apply(Math, arr);

    随机数:Math.random(); 0<=r<1
    任意min-max:
    Math.floor(Math.random() * (max - min +1) + min);

    /*随机生成四位验证码*/
    //Step1:数组:所有字母、数字
    var codes = [];
    for(var i = 48; i <= 57; codes.push(i), i++);
    for(var i = 65; i <= 90; codes.push(i), i++);
    for(var i = 97; i <= 122; codes.push(i), i++);

    function getCode(){
    var arr = [];
    for(var i = 0; i < 4; i++){//0-61之间取随机数
    var index = Math.floor(Math.random()*(60-0+1) + 0);
    var char = String.fromCharCode(codes[index]);
    arr.push(char);
    }
    return arr.join("");
    }

    while(true){
    var code = getCode();
    var input = prompt("输入验证码:" + code);
    var reg = /^[a-zA-Z0-9]{4}$/;
    if(reg.test(input)){
    if(code.toLowerCase() == input.toLowerCase()){
    document.write("登录成功");
    break;
    }else{
    alert("验证码输入错误!");
    }
    }
    }

    Date对象:封装一个时间点数据,提供对时间、日期的常用API
    创建:var date = new Date();
    1.创建Date类型对象; 2.自动获得浏览器当前时间点!
    自定义时间:var date = new Date("2015-6-9 16:47");
    1.创建Date类型对象; 2.自定义一个具体时间点

    *Date对象中,
    保存的是从1970年1月1日 0:00:00到现在的毫秒数
    var date = new Date();

    API:
    1.每个分量都有一对get/set方法,获取/设置该分量的值!
    2.命名:年/月/日 没有s,时,分,秒 有s
    3.取值、赋值:除了每月中的日之外,其余都是从0开始,到-1结束
    每月中的日,从1开始,带31结束
    月:取值时,要+1修正;赋值是,-1修正
    星期://日 一 ............ 六
    //0 1 6

    日期计算:两日期对象相减,得到毫秒数
    时间做+:var nowMs = date.getTime(); 返回时间毫秒数
    var nextMs = nowMs + 5*60*1000;
    var next = new Date(nextMs);
    使用毫秒做计算,不改变原时间对象!需要重新封装时间对象
    最大仅能算到“天数”。再算“月数”,无法确定每月天数。


    day09
    回顾:
    Date对象:内部封装了一个毫秒数
    创建日期对象:
    var date = new Date("2016/7/4");PPT上 new Date("2016-7-4");仅兼容chrome
    API
    1.每个分量都有一对get/set方法
    2.命名:年月日星期 不带s;时分秒带s
    3.值范围:月中的日:1-31;其他:0-减1

    计算:1.两日期相减,得到毫秒数
    2.日期+/- 天小时分秒:用毫秒
    3部:1.var ms = date.getTime();
    2.ms = ms +/- 毫秒数
    3.var newDate = new Date(ms);

    正课:
    3.任意分量的计算:
    先取出分量值,做计算,再set回去!

    var now = new Date();
    var day = now.getDate();//4
    day -= 10;//-6
    now.setDate(day);
    document.write(now);

    date.setXXX();1.自动调整进制
    2.*直接修改原日期对象*
    如何保留原日期对象?先new出新Date对象,再set
    var newDate = new Date(oldDate.getTime());

    日期格式转换:
    date.toLocaleString();//获得日期和时间的本地格式
    date.toLocaleDateString();//仅获得日期部分的本地格式
    date.toLocaleTimeString();//仅获得时间部分的本地格式

    日期格式转换:都要自定义format(date)方法!
    function format(date){
    var week = ["日", "一", "二", "三", "四", "五", "六"];
    var y = date.getFullYear() + "年";
    var m = date.getMonth() + 1 + "月";
    var d = date.getDate() + "日";

    var w = " 星期" + week[date.getDay()];

    var h = date.getHours();
    var am = h >= 12 ? " 上午 " : " 下午 ";
    h = h > 12 ? h - 12 : h;
    h = h < 10 ? "0" + h : "" + h;

    var mi = date.getMinutes();
    mi = mi < 10 ? "0" + mi : "" + mi;

    var s = date.getSeconds();
    s = s < 10 ? "0" + s : "" + s;

    var str = y + m + d + w + am + h + ":" + mi + ":" + s;
    return str;
    }

    Number类型 API:
    num.toFixed(n); 按n位小数四舍五入,*返回一个字符串*!
    何时使用:在计算之后,显示结果是,*最后调用toFixed方法*
    vs Math.round(num):只能取整 返回一个数Number

    num.toString(n):按n进制输出数字的字符串格式

    错误处理:
    什么是错误处理:导致程序运行停止的运行时异常状态
    什么是错误处理:在出现异常状态是,保证程序不停止的机制
    如何错误处理:
    错误类型:Error类型:所有错误对象的父类型
    6种子类型:EvalError,
    RangeError:参数超出范围
    比如:num.toFixed(n) n<0 抛出RangeError
    ReferenceError:引用错误:找不到对象
    比如:只要使用未声明的变量时,都要抛出ReferenceError
    SyntaxError:语法错误!修改源代码就可以解决!
    TypeError:错误的使用了类型和类型的方法!
    URIError:URI错误
    如何处理错误:
    try{
    可能出错的代码
    }catch(err){只要抛出错误,都要创建一个Error对象
    错误处理的代码
    1.获得错误信息:err.name 类型
    2.根据错误的类型,执行不同的处理
    }[finally{可有可无
    //程序中使用了大对象!一样要在finally中主动释放
    无论是否出错,都必须执行的代码
    }]

    能用if...else解决的问题,就不用try...catch!
    何时使用try...catch?try...catch处理的是无法预料的问题!

    主动抛出异常:如何告知方法调用者出错?
    thow new Error("自定义的错误信息");

    下午:
    Function对象:
    1.以声明方式定义方法:放前放后无所谓
    function 方法名(参数列表){方法体;return 返回值}
    2.以创建对象方式定义方法:必须定义在使用之前!
    var 方法名 = new Function("参数1", ..., "方法体;return 返回值");
    只有声明方式的方法定义才被提前解析!——方法声明提前

    重载:方法,根据传入的参数列表不同,执行不同的任务
    js支不支持重载:语法不支持,但是可以通过 arguments对象 模拟重载效果

    arguments对象:方法对象中保存所有参数的类数组对象
    类数组对象(object like array):长的像数组的对象
    *方法内,自动创建!直接使用!*
    arguments.length:保存变量的个数
    arguments[i]:访问传入的第i + 1个变量

    3.使用匿名函数赋值的方式定义方法:
    匿名函数:没有方法名的函数定义!
    var compare = function(a, b){return a-b;}

    鄙视题:js中方法定义的方式有几种:3种!
    A.function compare(a, b){return a - b}
    **************************************************************************
    B.var compare = function(a, b){return a - b;}
    C.var compare = new Function("a", "b", "return a- b;");
    D.var compare = new Function(a, b, return a- b;); X

    function isEmpty(str){
    if(str === undefined){
    return true;
    }else if(str == null){
    return true;
    }else{
    var reg = /^s*$/;
    return reg.test(str);
    }
    }

    var ltrim = function(str){
    var reg = /^s+/;
    return str.replace(reg, "");
    }
    var rtrim = function(str){
    var reg = /s+$/;
    return str.replace(reg, "");
    }

    匿名函数2个用途:
    1、回调函数:函数何时执行,程序员不需要控制!
    由所在环境执行!
    比较器!
    //var compare = function(a, b){return a - b;} arr.sort(compare);
    arr.sort(function(a, b){return a - b;})
    事件处理函数:onclick = "calc(12)";
    2、自调函数:匿名函数自己调用自己!
    当函数不需要重复使用时,使用匿名函数自调。
    语法:
    (function(参数...){
    方法体;
    })(参数值...);
    在函数定义的位置立即执行!

    闭包:函数外使用了不属于自己的局部变量
    何时使用闭包?保护局部变量

    day10
    回顾
    1. 闭包
    判断闭包3特点:
    1. 嵌套函数
    2. 内层函数操作了外层函数的局部变量
    3. 外层函数将内层函数返回到外部
    被全局变量保存住

    判断闭包执行结果:
    *1. 外层函数被调用几次,就有几个受保护的局部变量副本
    2. 反复调用来自一个闭包的函数,受保护的局部变量就变化几次

    正课:
    1. 面向对象
    1. 创建自定义对象
    2. ****继承

    1. 面向对象:在程序中都是用一个对象来描述现实中一个具体的东西;
    现实中的一个东西都包含属性和功能:
    属性:描述一个东西特点的变量
    功能:东西可以执行操作
    什么是对象:封装多个数据的存储空间
    什么是自定义对象:封装现实中一个东西的属性和功能的存储空
    间。现实中东西的属性会成为对象中的属性变量。现实中的东西的功能,会成为对象中
    的方法(函数)

    2. 创建自定义对象:3种方式:
    1. var obj = {'属性名1':值1,
    '属性名2':值2,
    ...
    '功能名1':function()
    {...}};
    js中一切都是对象!所有对象的底层都是hash数组

    属性:如何访问属性:2种:obj.属性名 obj["属性名"]
    访问对象中不存在的属性
    (访问数组中不存在的下标):不会出错,返回undefined
    强行给不存在属性赋值,不报错!js会自动创建同名属性

    如何判断某个对象是否包含指定成员:3种
    1. obj.hasOwnProperty("成员名");
    2. "属性名" in 对象
    如果找到,返回true,否则返回false
    3. 直接使用 obj.属性名 作为条件:
    arr.indexOf !== undefined
    如果不包含,返回undefined ————> false
    如果包含,返回值或function ————> true
    何时省略:判断方法是否存在时,可省略 !==
    如果确定属性值一定
    不是null, 0, "", NaN 也可省略

    方法:如何在方法中,访问当前对象自己:
    ****this关键字:运行时,指代正在*调用*方法的对象
    (.前的对象)
    this本质是window下唯一的一个指针,指向当前正在
    调用方法的对象

    如何在方法内,访问当前对象自己的属性:this.属性名
    **在方法内访问当前对象自己的属性,必须用this.属性

    省略this,默认访问活动对象和window中的变量(闭
    包除外)

    ***this和定义在哪无关!仅和调用时使用的当前对象有

    ***如果无主的调用或复制,默认this都是window!

    PM:
    正课:
    1. ***面向对象:继承
    面向对象三大特点:封装 继承 多态
    封装:将描述同一个东西的属性和方法,定义在一个对象中
    继承:父对象中的属性和方法,子对象可直接使用
    多态:同一个对象,在不同情况下,呈现不同的状态
    重载:同一方法名,传入参数不同,执行不同的操作
    重写:子对象觉得父对象的成员不好用,可自己定义一
    个,覆盖父对象的成员

    创建对象:3种:
    1. 对象直接量
    var obj = {"属性名":值, ..., "方法名":function(){...}};

    2. var obj = new Object();//创建一个空对象
    obj.属性名 = 值;
    obj.方法名 = function(){... this.属性名 ...};

    3. 利用构造函数*反复*创建*相同结构*的对象
    构造函数:描述一类对象结构的特殊函数
    2步:
    1. 定义构造函数
    function 构造函数名|类型名(属性参数1, ...){
    this.属性名 = 属性参数1;
    //在当前正在创建的对象中创建一个属性名
    //赋值为属性参数1的值
    ...
    this.方法名 = function(){
    ...this.属性名...
    }
    }
    2. 利用构造函数创建对象
    var obj = new 构造函数名|类型名(属性值1, ...);
    new:1. 创建一个空对象:new obj = {};
    2. 利用空对象,调用构造函数
    构造函数在空对象中添加属性和
    方法
    3. 设置新对象的 __proto__ 指向构造函数的
    prototype对象
    4. 返回新对象的地址

    继承:js中一切继承都是用原型对象实现的!
    原型对象:每个函数对象都有一个原型对象
    构造函数的原型对象负责保存所有子对象共享的成员!
    建议:所有子对象共享的方法,都应定义在构造函数的原型对象中。———
    —避免重复定义方法对象,浪费内存。
    说明:其实所有内置类型的API都是定义在类型.prototype

    扩展对象属性:2种扩展:
    1. 扩展共有属性:通过构造函数.prototype添加的属性
    2. 扩展自有属性:通过某一具体子对象添加属性
    判断自有属性或扩展属性:
    1. 判断自有属性:obj.hasOwnProperty("属性名");
    2. 判断共有属性:"属性名" in obj && !obj.hasOwnProperty("属性名")
    在原型对象关系中包含 且 子对
    象自己*没有*

    删除属性:delete 对象.属性名
    *仅能删除当前对象自己的属性,无法删除共有属性
    全局变量:3种
    var n = 1; window.n = 1; window["n"] = 1;
    不能delete 不能delete 能delete

    原型链:由各级对象的 __proto__ 逐级继承形成的关系
    获得任意对象的父级原型对象:Object.getPrototypeOf(子对象) =》子对象.__proto__
    检查对象的父对象:父对象.isPrototypeOf(子对象);


    day11
    面向对象:封装 继承 多态
    1. 创建对象:3种:4种:
    1. 直接量:var obj = {"属性名":值, ..., "方法名":function(){}};
    __proto__ ————> Object.prototype
    2. new关键字:var obj = new Object();
    obj.属性名 = 值;
    ...
    obj.方法名 = function(){}
    3. 使用构造函数反复创建相同结构的对象:2步
    1. 定义构造函数:
    function 构造函数名(属性参数, ...){
    this.属性名 = 属性参数;
    if(!构造函数名.prototype.方法名){
    构造函数名.prototype.方法名 =
    function(){}
    }
    }
    2. 使用new创建对象同时,调用构造函数:
    var obj = new 构造函数名(属性值, ...);
    4. Object.create(父对象, {扩展属性的列表对象});

    2. this:指代当前正在调用方法的对象
    this和定义在哪无关!仅和调用时使用的对象有关!
    所有无主(不用var赋值的变量,匿名函数)都是window的

    3. 原型,原型链,继承:
    原型:保存所有子对象共有属性和方法的对象!
    所有函数都有prototype,指向自己的原型对象
    所有对象都有 __proto__ ,指向自己父级原型对象
    所有原型对象都有constructor,指回原型对应的构造函数

    原型链:所有父子级对象间由 __proto__ 形成的多级引用关系
    ————>*多级*继承

    原型相关API:
    1. 判断自有属性和共有属性:
    1. 判断自有:obj.hasOwnProperty("属性名");
    2. 判断原型链上的属性:2种
    判断不包含:if(!("属性名" in obj/原型))
    if(obj.属性名 === undefined)
    if(!obj.属性名)
    3. 仅判断共有:必须满足两个条件
    !obj.hasOwnProperty("属性名") && obj.属性名
    2. 获得任意对象的原型:
    obj.__proto__ X
    Object.getPrototypeOf(obj)
    3. 判断父对象是否在子对象的原型链上
    父对象.isPrototypeOf(子对象)

    ***检测一个对象是不是数组类型:4种:
    1. Array.prototype.isPrototypeOf(obj);
    2. obj instanceof Array
    对象 是不是 构造函数 的实例
    3. obj.constructor == Array 仅判断直接父级
    4. 利用当前对象,强行调用原始的toString方法
    Object.prototype.toString.call(obj) == "[object Array]"
    apply(obj)
    继承:
    为什么要继承:代码重用!节省空间!
    1. 直接继承对象:想方设法修改对象的 __proto__ 属性
    3种:
    1. 仅修改一个对象的 __proto__
    Object.setPrototypeOf(子对象, 父对象);
    2. 通过修改构造函数的原型对象,实现批量修改后续子对象的继承关系。
    构造函数.prototype = 父对象
    强调:仅影响之后创建的对象的继承关系
    之前创建的对象依然继承旧构造函
    数.prototype
    3. var obj = Object.create(父对象[, {属性列表}])
    创建一个空对象,
    继承父对象中的属性,
    继承同时可再扩展属性和方法

    2. 仅继承结构:模拟java中的继承
    function 父类型构造函数(属性参数1, 属性参数2){
    this.属性1 = 属性参数1;
    this.属性2 = 属性参数2;
    }

    function 子类型构造函数(属性参数1, 属性参数2, 属性参数3){
    父类型构造函数.call(this, 属性参数1, 属性参数2);
    this.属性3 =属性参数3;
    }

    var obj = new 子类型构造函数(值1, 值2, 值3);

  • 相关阅读:
    Loading CSS without blocking render
    总结Web应用中基于浏览器的安全漏洞
    React Native通信机制详解
    HTML Imports
    编程语言和它们的创造者
    USB Transfer and Packet Sizes
    灰色心情
    c++ 深入理解虚函数
    在VS2012中采用C++中调用DLL中的函数(4)
    在C++中调用DLL中的函数(3)
  • 原文地址:https://www.cnblogs.com/skorzeny/p/5668527.html
Copyright © 2020-2023  润新知