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编号,就等效于处理编号对应的文字。 转义字符:专门表示非打印字符以及特殊符号 如何使用转义字符:\特殊符号 比如:\n 换行 、\t 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("...");//包装类型对象
转义字符:代替字符串中的非打印字符:\n \t 如果字符串内容中包含和语法冲突的特殊字符,可用\转为普通字符 比如:console.log("\tjs是互联网\"第一大语言\"");
字符串内容一旦创建不能改变! 如果修改,都要创建新字符串,保存新结果,替换旧字符串 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个,多了不限 手机号:\+86\s1[3578]\d{9} 用户名:\w{6,8}
day08 回复: []:备选字符集,只能多选一。一个[]只能匹配一位字符 比如:我[去草]:我去 我草 []内:开头^:除了xx都行:[01235689] ——> [^47] -:表示备选字符的范围 :[a-z] [0-9] [A-Z]
预定义字符集: [0-9] ——> \d [a-zA-Z_] ——> \w \s:空字符: \n \t 空格
量词:修饰前一位字符出现的次数 {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);
转自 https://www.cnblogs.com/skorzeny/p/5668527.html
|