JavaScript(7月22号)

HTML+CSS+JS        属于前端三剑客

HTML:基于标签编写网页文档的结构,版本是HTML2,简称H5

CSS:基于选择器和属性美化,布局排版网页,版本是CSS3

JS:嵌入在网页中的编程语言,也称为"脚本语言",负责编写用户与网页的交互操作

        变量

        流程控制

        对象

        数组

        函数

Java和JavaScript的区别

        1、Java是强类型语言,静态类型语言

        2、JavaScript是弱类型语言,动态类型语言

JS的继承依靠的是原型链

        1、同一个构造方法构造出来的对象拥有一个__proto__指针,指向同一个原型对象

        2、构造方法身上有一个prototype指针,与该构造方法构造出来的所有对象的__proto__指向同一个原型对象

        3、通过"指针.__proto__.成员"或者"构造方法.prototype.成员" 可以设置一个所有构造方法构造出来的对象都可以继承的成员

        4、通过"Object.prototype.成员"可以设置一个任意构造方法构造出来的对象都可以继承的成员

试题1:什么是原型对象,什么是对象原型

        他们都是一个东西,构造方法身上有一个prototype指针,与该构造方法构造出来的所有对象的__proto__指向同一个原型对象

试题2:什么是原型链

        所有的对象和构造方法身上都有指针,指向同一个原型对象,原型对象身上有指针指向其继承的构造方法的原型对象。最顶层的是Object的原型对象。这种由子构造函数及其父辈构造函数的原型对象组成单向链表称为原型链,在对象身上访问成员的时候,会沿着原型链一直向上追溯,如果追溯到顶层Object的原型对象都找不到,返回undefined。

JavaScript整理

1、基本语法:

        与Java基本一致,虽然JavaScript不强制每句语句后面都要加“;”,但是如果不加“;”可能会在运行时导致运行结果与期望值不一致。

2、数据类型和变量:

        1、number

                JavaScript不区分整数和浮点数,即(byte、short、int、long、float、double),统一用number表示

        2、字符串

                JavaScript中,字符串以单引号或双引号括起来,和Java的区别是Java中单引号只能表示字符,JavaScript中单引号和双引号都表示字符串

        3、布尔型

                JavaScript中,Boolean的表示和Java一样,一个布尔值只有true和false两种值

        在JavaScript中,&&运算、||运算、!运算与Java一致。

        4、但是在比较运算符上,javaScript有“==”和“===”两种运算符,“==”比较时会自动转换数据类型再比较,这样会产生很多奇怪的结果;“===”比较时不会自动转换数据类型,数据不一致就返回false,一致了再比较。由于JavaScript的设计缺陷,我们最好始终使用“===”进行比较。

        5、null和undefined

                “null”表示一个空值,它与undefined的区别是“null”代表的是空值,一般情况下代表的是有一个变量存在但没有赋值;而undefined代表的是这个变量不存在。

        6、数组

                JavaScript中创建数组使用Array(),但是更推荐直接使用[]创建数组

        7、对象

                javaScript对象的键都是字符串类型,值可以是任意数据类型,JavaScript中的对象只需要一个构造方法,就可以创造对象,不需要像Java一样声明变量。

        8、变量

                变量在JavaScript中就使用一个变量名表示,变量名是大小写英文、数字、$、_的组合,且不能用数字开头,变量名也不能是JavaScript的关键字。在JavaScript中使用“=”给变量赋值,使用“var”可以给一个变量不同类型的值

                使用var申明的变量则不是全局变量,它的范围被限制在该变量被申明的函数体内(函数的概念将稍后讲解),同名变量在不同的函数体内互不冲突。

                为了修补JavaScript这一严重设计缺陷,ECMA在后续规范中推出了strict模式,在strict模式下运行的JavaScript代码,强制通过var申明变量,未使用var申明变量就使用的,将导致运行错误。

3、字符串

        JavaScript的字符串用' '或" "括起来的字符表示;

        转义字符\可以转义很多字符,例如:\n表示换行,\t表示制表符;

        1、多行字符串

                多行字符串用\n写起来比较费劲,最新的ES6标准新增了一种多行字符串的表示方法,用反引号“...”表示

        2、模板字符串

                要把多个字符串连接起来,可以用“+”连接

        3、操作字符串

                要获得字符串某个指定位置的字符,使用类似Array的下标操作,索引号从0开始;字符串是不可变的,如果对字符串的某个索引赋值,不会有任何错误,但是也没有任何效果。

                toUpperCase:把一个字符串全部变成大写

                toLowerCase:把一个字符串全部变成小写

                indexOf:会搜索指定字符串出现的位置

                subString:返回指定索引区的子串

4、数组

        1、要取得Array的长度,直接访问length属性

                直接给Array的length赋值会导致Array大小变化;

        2、Array可以通过索引把对应的元素修改为新的值,因此,对Array的索引进行赋值会直接修改这个Array

        3、slice:slice()对应String的subString()版本,它截取Array的部分元素,然后返回一个新的Array(截取不包括尾部的一个元素);

        4、push和pop:push()向Array的末尾添加若干元素,pop()则把Array的最后一个元素删除掉;

        5、UNshift和shift:unshift()在Array的头部添加若干元素,shift()则把Array的第一个元素删掉;

        6、sort:可以对当前Array进行排序,它会直接修改当前Array的元素位置,直接调用时,按照默认顺序排序;

        7、reverse:把整个Array的元素给调反,即反转;

        8、splice:修改Array的万能方法

        9、concat:把当前的Array和另一个Array连接起来,并返回一个新的Array;

        10、join:把当前Array的每个元素都用指定的字符串连接起来,然后返回连接后的字符串;

       

5、对象

        

JavaScript的对象是一种无序的集合数据类型,它由若干键值对组成。

JavaScript的对象用于描述现实世界中的某个对象。例如,为了描述“小明”这个淘气的小朋友,我们可以用若干键值对来描述他:

JavaScript用一个{...}表示一个对象,键值对以xxx: xxx形式申明,用,隔开。注意,最后一个键值对不需要在末尾加,,如果加了,有的浏览器(如低版本的IE)将报错。

上述对象申明了一个name属性,值是'小明'birth属性,值是1990,以及其他一些属性。最后,把这个对象赋值给变量xiaoming后,就可以通过变量xiaoming来获取小明的属性了:

访问属性是通过.操作符完成的,但这要求属性名必须是一个有效的变量名。如果属性名包含特殊字符,就必须用''括起来:

xiaohong的属性名middle-school不是一个有效的变量,就需要用''括起来。访问这个属性也无法使用.操作符,必须用['xxx']来访问:

也可以用xiaohong['name']来访问xiaohongname属性,不过xiaohong.name的写法更简洁。我们在编写JavaScript代码的时候,属性名尽量使用标准的变量名,这样就可以直接通过object.prop的形式访问一个属性了。

实际上JavaScript对象的所有属性都是字符串,不过属性对应的值可以是任意数据类型。

如果访问一个不存在的属性会返回什么呢?JavaScript规定,访问不存在的属性不报错,而是返回undefined

'use strict';

var xiaoming = {
    name: '小明'
};

 Run

由于JavaScript的对象是动态类型,你可以自由地给一个对象添加或删除属性:

如果我们要检测xiaoming是否拥有某一属性,可以用in操作符:

不过要小心,如果in判断一个属性存在,这个属性不一定是xiaoming的,它可能是xiaoming继承得到的:

因为toString定义在object对象中,而所有对象最终都会在原型链上指向object,所以xiaoming也拥有toString属性。

要判断一个属性是否是xiaoming自身拥有的,而不是继承得到的,可以用hasOwnProperty()方法:

                

 

JS的继承依靠的是原型链

        1、同一个构造方法构造出来的对象拥有一个__proto__指针,指向同一个原型对象

        2、构造方法身上有一个prototype指针,与该构造方法构造出来的所有对象的__proto__指向同一个原型对象

        3、通过"指针.__proto__.成员"或者"构造方法.prototype.成员" 可以设置一个所有构造方法构造出来的对象都可以继承的成员

        4、通过"Object.prototype.成员"可以设置一个任意构造方法构造出来的对象都可以继承的成员

试题1:什么是原型对象,什么是对象原型

        他们都是一个东西,构造方法身上有一个prototype指针,与该构造方法构造出来的所有对象的__proto__指向同一个原型对象

试题2:什么是原型链

        所有的对象和构造方法身上都有指针,指向同一个原型对象,原型对象身上有指针指向其继承的构造方法的原型对象。最顶层的是Object的原型对象。这种由子构造函数及其父辈构造函数的原型对象组成单向链表称为原型链,在对象身上访问成员的时候,会沿着原型链一直向上追溯,如果追溯到顶层Object的原型对象都找不到,返回undefined。

6、条件判断

        

JavaScript使用if () { ... } else { ... }来进行条件判断。例如,根据年龄显示不同内容,可以用if语句实现如下:

其中else语句是可选的。如果语句块只包含一条语句,那么可以省略{}

多行条件判断

如果还要更细致地判断条件,可以使用多个if...else...的组合:

上述多个if...else...的组合实际上相当于两层if...else...

但是我们通常把else if连写在一起,来增加可读性。这里的else略掉了{}是没有问题的,因为它只包含一个if语句。注意最后一个单独的else不要略掉{}

7、循环

        

循环

for ... in

for循环的一个变体是for ... in循环,它可以把一个对象的所有属性依次循环出来:

要过滤掉对象继承的属性,用hasOwnProperty()来实现:

由于Array也是对象,而它的每个元素的索引被视为对象的属性,因此,for ... in循环可以直接循环出Array的索引:

while

for循环在已知循环的初始和结束条件时非常有用。而上述忽略了条件的for循环容易让人看不清循环的逻辑,此时用while循环更佳。

while循环只有一个判断条件,条件满足,就不断循环,条件不满足时则退出循环。比如我们要计算100以内所有奇数之和,可以用while循环实现:

do ... while

最后一种循环是do { ... } while()循环,它和while循环的唯一区别在于,不是在每次循环开始的时候判断条件,而是在每次循环完成的时候判断条件:

do { ... } while()循环要小心,循环体会至少执行1次,而forwhile循环则可能一次都不执行。

8、函数定义和调用

        

定义函数

在JavaScript中,定义函数的方式如下:

上述abs()函数的定义如下:

  • function指出这是一个函数定义;
  • abs是函数的名称;
  • (x)括号内列出函数的参数,多个参数以,分隔;
  • { ... }之间的代码是函数体,可以包含若干语句,甚至可以没有任何语句。

调用函数

调用函数时,按顺序传入参数即可:

由于JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数:

传入的参数比定义的少也没有问题:

此时abs(x)函数的参数x将收到undefined,计算结果为NaN

要避免收到undefined,可以对参数进行检查:

rest参数

由于JavaScript函数允许接收任意个参数,于是我们就不得不用arguments来获取所有参数:

为了获取除了已定义参数ab之外的参数,我们不得不用arguments,并且循环要从索引2开始以便排除前两个参数,这种写法很别扭,只是为了获得额外的rest参数,有没有更好的方法?

ES6标准引入了rest参数,上面的函数可以改写为:

rest参数只能写在最后,前面用...标识,从运行结果可知,传入的参数先绑定ab,多余的参数以数组形式交给变量rest,所以,不再需要arguments我们就获取了全部参数。

如果传入的参数连正常定义的参数都没填满,也不要紧,rest参数会接收一个空数组(注意不是undefined)。

9、方法

        

在一个对象中绑定函数,称为这个对象的方法。

在JavaScript中,对象的定义是这样的:

但是,如果我们给xiaoming绑定一个函数,就可以做更多的事情。比如,写个age()方法,返回xiaoming的年龄:

绑定到对象上的函数称为方法,和普通函数也没啥区别,但是它在内部使用了一个this关键字,这个东东是什么?

在一个方法内部,this是一个特殊变量,它始终指向当前对象,也就是xiaoming这个变量。所以,this.birth可以拿到xiaomingbirth属性。

apply

虽然在一个独立的函数调用中,根据是否是strict模式,this指向undefinedwindow,不过,我们还是可以控制this的指向的!

要指定函数的this指向哪个对象,可以用函数本身的apply方法,它接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。

装饰器

利用apply(),我们还可以动态改变函数的行为。

JavaScript的所有对象都是动态的,即使内置的函数,我们也可以重新指向新的函数。

现在假定我们想统计一下代码一共调用了多少次parseInt(),可以把所有的调用都找出来,然后手动加上count += 1,不过这样做太傻了。最佳方案是用我们自己的函数替换掉默认的parseInt()

10、Date   

在JavaScript中,Date对象用来表示日期和时间。

要获取系统当前时间,用:

注意,当前时间是浏览器从本机操作系统获取的时间,所以不一定准确,因为用户可以把当前时间设定为任何值。

如果要创建一个指定日期和时间的Date对象,可以用:

你可能观察到了一个非常非常坑爹的地方,就是JavaScript的月份范围用整数表示是0~11,0表示一月,1表示二月……,所以要表示6月,我们传入的是5!这绝对是JavaScript的设计者当时脑抽了一下,但是现在要修复已经不可能了。

 JavaScript的Date对象月份值从0开始,牢记0=1月,1=2月,2=3月,……,11=12月。

第二种创建一个指定日期和时间的方法是解析一个符合ISO 8601格式的字符串:

但它返回的不是Date对象,而是一个时间戳。不过有时间戳就可以很容易地把它转换为一个Date

 使用Date.parse()时传入的字符串使用实际月份01~12,转换为Date对象后getMonth()获取的月份值为0~11。

时区

Date对象表示的时间总是按浏览器所在时区显示的,不过我们既可以显示本地时间,也可以显示调整后的UTC时间:

那么在JavaScript中如何进行时区转换呢?实际上,只要我们传递的是一个number类型的时间戳,我们就不用关心时区转换。任何浏览器都可以把一个时间戳正确转换为本地时间。

时间戳是个什么东西?时间戳是一个自增的整数,它表示从1970年1月1日零时整的GMT时区开始的那一刻,到现在的毫秒数。假设浏览器所在电脑的时间是准确的,那么世界上无论哪个时区的电脑,它们此刻产生的时间戳数字都是一样的,所以,时间戳可以精确地表示一个时刻,并且与时区无关。

所以,我们只需要传递时间戳,或者把时间戳从数据库里读出来,再让JavaScript自动转换为当地时间就可以了。

11、regexp

所以我们判断一个字符串是否是合法的Email的方法是:

  1. 创建一个匹配Email的正则表达式;

  2. 用该正则表达式去匹配用户的输入来判断是否合法。

因为正则表达式也是用字符串表示的,所以,我们要首先了解如何用字符来描述字符。

在正则表达式中,如果直接给出字符,就是精确匹配。用\d可以匹配一个数字,\w可以匹配一个字母或数字,所以:

  • '00\d'可以匹配'007',但无法匹配'00A'

  • '\d\d\d'可以匹配'010'

  • '\w\w'可以匹配'js'

.可以匹配任意字符,所以:

  • 'js.'可以匹配'jsp''jss''js!'等等。

RegExp

有了准备知识,我们就可以在JavaScript中使用正则表达式了。

JavaScript有两种方式创建一个正则表达式:

第一种方式是直接通过/正则表达式/写出来,第二种方式是通过new RegExp('正则表达式')创建一个RegExp对象。

两种写法是一样的:

注意,如果使用第二种写法,因为字符串的转义问题,字符串的两个\\实际上是一个\

先看看如何判断正则表达式是否匹配:

RegExp对象的test()方法用于测试给定的字符串是否符合条件。

切分字符串

用正则表达式切分字符串比用固定的字符更灵活,请看正常的切分代码:

嗯,无法识别连续的空格,用正则表达式试试:

无论多少个空格都可以正常分割。加入,试试:

再加入;试试:

如果用户输入了一组标签,下次记得用正则表达式来把不规范的输入转化成正确的数组。

分组

除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用()表示的就是要提取的分组(Group)。比如:

^(\d{3})-(\d{3,8})$分别定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码:

如果正则表达式中定义了组,就可以在RegExp对象上用exec()方法提取出子串来。

exec()方法在匹配成功后,会返回一个Array,第一个元素是正则表达式匹配到的整个字符串,后面的字符串表示匹配成功的子串。

exec()方法在匹配失败时返回null

提取子串非常有用。来看一个更凶残的例子:

这个正则表达式可以直接识别合法的时间。但是有些时候,用正则表达式也无法做到完全验证,比如识别日期:

对于'2-30''4-31'这样的非法日期,用正则还是识别不了,或者说写出来非常困难,这时就需要程序配合识别了。

贪婪匹配

需要特别指出的是,正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。举例如下,匹配出数字后面的0

由于\d+采用贪婪匹配,直接把后面的0全部匹配了,结果0*只能匹配空字符串了。

必须让\d+采用非贪婪匹配(也就是尽可能少匹配),才能把后面的0匹配出来,加个?就可以让\d+采用非贪婪匹配:

全局搜索

JavaScript的正则表达式还有几个特殊的标志,最常用的是g,表示全局匹配:

全局匹配可以多次执行exec()方法来搜索一个匹配的字符串。当我们指定g标志后,每次运行exec(),正则表达式本身会更新lastIndex属性,表示上次匹配到的最后索引:

全局匹配类似搜索,因此不能使用/^...$/,那样只会最多匹配一次。

正则表达式还可以指定i标志,表示忽略大小写,m标志,表示执行多行匹配。

12、JSON

序列化

让我们先把小明这个对象序列化成JSON格式的字符串:

'use strict';

var xiaoming = {
    name: '小明',
    age: 14,
    gender: true,
    height: 1.65,
    grade: null,
    'middle-school': '\"W3C\" Middle School',
    skills: ['JavaScript', 'Java', 'Python', 'Lisp']
};

反序列化

拿到一个JSON格式的字符串,我们直接用JSON.parse()把它变成一个JavaScript对象:

JSON.parse()还可以接收一个函数,用来转换解析出的属性:

'use strict';

13、创建对象

当我们用obj.xxx访问一个对象的属性时,JavaScript引擎先在当前对象上查找该属性,如果没有找到,就到其原型对象上找,如果还没有找到,就一直上溯到Object.prototype对象,最后,如果还没有找到,就只能返回undefined

构造函数

除了直接用{ ... }创建一个对象外,JavaScript还可以用一种构造函数的方法来创建对象。它的用法是,先定义一个构造函数:

忘记写new怎么办

如果一个函数被定义为用于创建对象的构造函数,但是调用时忘记了写new怎么办?

在strict模式下,this.name = name将报错,因为this绑定为undefined,在非strict模式下,this.name = name不报错,因为this绑定为window,于是无意间创建了全局变量name,并且返回undefined,这个结果更糟糕。

所以,调用构造函数千万不要忘记写new。为了区分普通函数和构造函数,按照约定,构造函数首字母应当大写,而普通函数首字母应当小写,这样,一些语法检查工具如jslint将可以帮你检测到漏写的new

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值