js
博客园
首页
新随笔
联系
管理
订阅
订阅
随笔- 33 文章- 181 评论- 320
javascript-ECMAScript
javascript介绍
Web前端有三层:
HTML:从语义的角度,描述页面结构
CSS:从审美的角度,描述样式(美化页面)
JavaScript:从交互的角度,描述行为(提升用户体验)
其中JavaScript基础又分为三个部分:
ECMAScript:JavaScript的语法标准。包括变量、表达式、运算符、函数、if语句、for语句等。
DOM:文档对象模型,操作网页上的元素的API。比如让盒子移动、变色、轮播图等。
BOM:浏览器对象模型,操作浏览器部分功能的API。比如让浏览器自动滚动。
JavaScript历史背景介绍
布兰登 • 艾奇(Brendan Eich,1961年~),1995年在网景公司,发明的JavaScript。
一开始JavaScript叫做LiveScript,但是由于当时Java这个语言特别火,所以为了傍大牌,就改名为JavaScript。如同“北大”和“北大青鸟”的关系。“北大青鸟”就是傍“北大”大牌。
同时期还有其他的网页语言,比如VBScript、JScript等等,但是后来都被JavaScript打败了,所以现在的浏览器中,只运行一种脚本语言就是JavaScript
JavaScript和ECMAScript的关系
JavaScript的发展:蒸蒸日上
http://2004.sina.com.cn/ http://2008.sina.com.cn/ http://2012.sina.com.cn/
上面三个网站可以感受一下网页技术的发展。
发展历程
JavaScript入门易学性
JavaScript对初学者比较友好。
JavaScript是有界面效果的(比如C语言只有白底黑字)。
JavaScript是弱变量类型的语言,变量只需要用var来声明。而Java中变量的声明,要根据变量的类型来定义。
JavaScript的组成
JavaScript基础分为三个部分:
ECMAScript:JavaScript的语法标准。包括变量、表达式、运算符、函数、if语句、for语句等。
DOM:操作网页上的元素的API。比如让盒子移动、变色、轮播图等。
BOM:操作浏览器部分功能的API。比如让浏览器自动滚动。
PS:JS机械重复性的劳动几乎为0,基本都是创造性的劳动。而不像HTML、CSS中margin、padding都是机械重复劳动。
JavaScript的特点
(1)简单易用:可以使用任何文本编辑工具编写,只需要浏览器就可以执行程序。
(2)解释执行(解释语言):事先不编译、逐行执行、无需进行严格的变量声明。
(3)基于对象:内置大量现成对象,编写少量程序可以完成目标
javascript语法
学习程序,是有规律可循的,就是程序是有相同的部分,这些部分就是一种规定,不能更改,我们成为:语法。
(1)JavaScript对换行、缩进、空格不敏感。
备注:每一条语句末尾要加上分号,虽然分号不是必须加的,但是为了程序今后要压缩,如果不加分号,压缩之后将不能运行。
(2)所有的符号,都是英语的。比如括号、引号、分号。
js代码的引入
在页面中,我们可以在body标签中放入标签对儿,标签对儿
变量和赋值
变量
var a = 100; //变量的定义和赋值
变量说明
变量名有命名规范:只能由英语字母、数字、下划线、美元符号$构成,且不能以数字开头,并且不能是JavaScript保留字,变量区分大小写也就是说A和a是两个变量。
js保留字
赋值
将等号右边的值,赋给左边的变量;等号右边的变量,值不变。
var a = "3";
var b = 2;
a = b
console.log(a)
console.log(b)
注释
// 我是单行注释
/*
多行注释1
多行注释2
*/
备注:sublime中,单行注释的快捷键是ctrl+/,多行注释的快捷键是ctrl+shift+/。
输入输出信息
弹出警告框:alert语句
alert(英文翻译为“警报”)的用途:弹出“警告框”。
控制台输出console.log("") 和输入框prompt()
console.log和prompt
代码示例:
上方代码中,用户输入的内容,将被传递到变量 a 里面。效果如下:
基础数据类型
变量里面能够存储数字、字符串等。和 python一样,js中定义变量的时候不必指定类型,变量会自动的根据存储内容的类型不同,来决定自己的类型。查看类型使用typeof方法。
数值类型:number
在JavaScript中,只要是数,就是数值型(number)的。无论整浮、浮点数(即小数)、无论大小、无论正负,都是number类型的。
var a = 100; //定义了一个变量a,并且赋值100
console.log(typeof a); //输出a变量的类型
console.log(typeof(a)); //输出a变量的类型
小数的保留
字符串类型:string
1.定义
var a = "abcde";
var b = '路飞'; //不区分单双引号
console.log(typeof a);
console.log(typeof b);
2.常用方法
方法 说明
.length #不加括号的是属性 返回长度
.trim() #得到一个新值 移除空白
.trimLeft() 移除左边的空白
.trimRight() 移除右边的空白
.concat(value, ...) #s1='hello';s.concat('xx');得到helloxx 拼接
.charAt(n) #n类似索引,从0开始,超过最大值返回''空字符串 返回第n个字符
.indexOf(substring, start) #这个start是从索引几开始找,没有返回-1 子序列位置
.substring(from, to) #不支持负数,所以一般都不用它,了解一下就行了 根据索引获取子序列
.slice(start, end) #var s1='helloworld';s1.slice(0,-5)看结果,就用它 切片
.toLowerCase() #全部变小写 小写
.toUpperCase() #全部变大写 大写
.split(delimiter, limit)#分隔,s1.splite(' '),后面还可以加参数s1.split(' ',2),返回切割后的元素个数 分割
chartAt() 返回指定索引的位置的字符
concat 返回字符串值,表示两个或多个字符串的拼接
match() 字符串匹配和正则匹配
replace(a,b) 将字符串a替换成字符串b
indexof()/search() 查找字符的下标,如果找到返回字符串的下标,找不到则返回-1 。
slice(start,end) 切片。左闭右开 分割数组 接收负参数
substr(start,length) 返回一个字符串:从指定位置开始,取指定字符数。
substring(indexStart,indexEnd) 切子字符串。顾头不顾尾
split('sep',n) 切割,根据n保留切割的数组长度
toLowerCase():转小写
toUpperCase():转大写
trim() 去除字符串两边的空白
布尔值:boolean
var b1 = false;
console.log(typeof b1)
空元素:null
var c1 = null;//空对象. object
console.log(c1)
未定义:undefined
var d1;
//表示变量未定义
console.log(typeof d1)
内置对象类型
数组:Array
1.数组的创建
var colors = ['red','color','yellow']; //字面量方式创建(推荐)
var colors2 = new Array();//使用构造函数(后面会讲)的方式创建 使用new关键词对构造函数进行创建对象
2.数组的赋值
var arr = [];
//通过下标进行一一赋值
arr[0] = 123;
arr[1] = '哈哈哈';
arr[2] = '嘿嘿嘿'
3.数组的常用方法
方法 说明
.length 数组的大小
.push(ele) 尾部追加元素
.pop() 获取尾部的元素
.unshift(ele) 头部插入元素
.shift() 头部移除元素
.slice(start, end) 切片
.reverse() #在原数组上改的 反转
.join(seq)#a1.join('+'),seq是连接符 将数组元素连接成字符串
.concat(val, ...) #连个数组合并,得到一个新数组,原数组不变 连接数组
.sort() 排序
.forEach() #讲了函数再说 将数组的每个元素传递给回调函数
.splice() #参数:1.从哪删(索引), 2.删几个 3.删除位置替换的新元素(可多个元素) 删除元素,并向数组添加新元素。
.map() #讲了函数再说 返回一个数组元素调用函数处理后的值的新数组
concat方法:列表的拼接
join方法:将数组中的元素使用指定的字符串连接起来,它会形成一个新的字符串
toString方法:将数组转换成字符串
slice(start,end):切片(左闭右开)
pop方法:删除尾元素
push方法:向数组末尾添加一个元素或多个元素,并返回新的长度
reverse()方法:翻转数组
sort()方法:排序
Array.isArray(被检测的值):判断是否为数组
shift():删除并返回数组的第一个元素
unshift():向数组的开头添加一个或更多元素,并返回新的长度
清空数组的几种方式
sort的问题
forEach方法,设定每一个元素执行某函数
map方法,循环每一个元素完成某操作返回新的值组成新数组
JSON对象
var str1 = '{"name": "chao", "age": 18}';
var obj1 = {"name": "chao", "age": 18};
// JSON字符串转换成对象
var obj = JSON.parse(str1);
// 对象转换成JSON字符串
var str = JSON.stringify(obj1);
遍历对象中的内容:
var a = {"name": "Alex", "age": 18};
for (var i in a){
console.log(i, a[i]);
}
日期:Date
1.定义
创建日期对象只有构造函数一种方式,使用new关键字
var myDate = new Date(); //创建了一个date对象
2.常用方法
复制代码
//创建日期对象
var myDate=new Date();
//获取一个月中的某一天
console.log(myDate.getDate());
//返回本地时间
console.log(myDate().toLocalString());//2018/5/27 下午10:36:23
复制代码
注意:以上getxxx的方法都是对时间的获取,如果要设置时间,使用setxxx,请参考链接:http://www.runoob.com/jsref/jsref-obj-date.html
RegExp对象
RegExp相关:用的比较多
RegExp相关
数学相关:Math
1.常用方法
其他方法
Math.ceil() 向上取整,'天花板函数'
Math.floor 向下取整,'地板函数'
max/min 求两个数的最大值和最小值
随机数 Math.random() 区间[0,1)
以上是咱们介绍的JS常用对象的方法,如果想参考更多内容,请参考链接:http://www.runoob.com/jsref/jsref-tutorial.html
数据类型之间的转换
parseInt() :字符串转数字
复制代码
var a = '5'
var a = parseInt(a);
console.log(typeof(a))
//带有自动净化的功能;只保留字符串最开头的数字,后面的中文自动消失。
console.log(parseInt("2018你真帅!!"));
//自动带有截断小数的功能:取整,不四舍五入。
var a = parseInt(5.8) + parseInt(4.7);
console.log(a);
var a = parseInt(5.8 + 4.7);
console.log(a);
复制代码
parseFloat() : 字符串转小数
var a = parseFloat('5.8')+ parseFloat('4.7');
console.log(a);
var a = parseFloat('5.8' + '4.7');
console.log(a);
String()和.toString:转字符串
var n1 = 123;
var str1 = String(n1);
console.log(typeof str1);
var num = 234;
console.log(num.toString())
Boolean():任何数据类型都可以转成布尔值
复制代码
var b1 = '123'; // true
var b3 = -123; // true
var b4 = Infinity; //表示正无穷大 true
var b2 = 0; // false
var b5 = NaN; //false
var b6; //表示undefined //false
var b7 = null; //false
复制代码
运算符
赋值运算符
以var x = 12,y=5来演示示例|
比较运算符
var x = 5;
算数运算符
var a = 5,b=2
'+': 字符串可相加,数字也可相加,字符串和数字也可以相加。值得注意的是,如果字符串和数字相加会自动把结果转换成字符串。如下:
console.log('吃了'+'么') //'吃了么'
console.log(12+3) //15
console.log('吃了'+3) //'吃了3'
'-':字符串 - 数值 = 数值
var a = "3";
var b = 2;
console.log(a-b) //1
console.log(b-a) //-1 字符串与数字之间相减的结果是数字
逻辑运算符
&& 逻辑与 ||逻辑或 !逻辑非
&&逻辑与,两侧条件都成立的时候才成立
||逻辑或,两侧条件有一个成立的时候就成立
!逻辑非 true变false,false变true
流程控制和与或非
流程控制
if单分支
if...else...
if...else if...else
case语句
while循环
do-while循环
for循环
三元运算符
函数
函数的定义
function 函数名字(){
}
语法说明
函数的调用
函数名字();
函数的参数和返回值:形参和实参
注意:实际参数和形式参数的个数,要相同。
注意:函数只能返回一个值,如果要返回多个值,只能将其放在数组或对象中返回。
console.log(sum(3, 4));
//函数:求和
function sum(a, b) {
return a + b;
}
伪数组:arguments
arguments代表的是实参。有个讲究的地方是:arguments只在函数中使用。
(1)返回函数实参的个数:arguments.length
复制代码
fn(2,4);
fn(2,4,6);
fn(2,4,6,8);
function fn(a,b,c) {
console.log(arguments);
console.log(fn.length); //获取形参的个数
console.log(arguments.length); //获取实参的个数
console.log("----------------");
}
复制代码
结果:
(2)之所以说arguments是伪数组,是因为:arguments可以修改元素,但不能改变数组的长短。举例:
复制代码
fn(2,4);
fn(2,4,6);
fn(2,4,6,8);
function fn(a,b) {
arguments[0] = 99; //将实参的第一个数改为99
arguments.push(8); //此方法不通过,因为无法增加元素
}
复制代码
匿名函数
自执行函数
函数的全局变量和局部变量
局部变量:
在JavaScript函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它(该变量的作用域是函数内部)。只要函数运行完毕,本地变量就会被删除。
全局变量:
在函数外声明的变量是全局变量,网页上的所有脚本和函数都能访问它。
变量生存周期:
JavaScript变量的生命期从它们被声明的时间开始。局部变量会在函数运行以后被删除。全局变量会在页面关闭后被删除。
作用域
首先在函数内部查找变量,找不到则到外层函数查找,逐步找到最外层。
几个例子:
例1
例2
例3:闭包
面向对象(了解)
创建对象的几种常用方式:
1.使用Object或对象字面量创建对象
2.工厂模式创建对象
3.构造函数模式创建对象
4.原型模式创建对象
使用Object或对象字面量创建对象
JS中最基本创建对象的方式:
var student = new Object();
student.name = "easy";
student.age = "20";
这样,一个student对象就创建完毕,拥有2个属性name以及age,分别赋值为"easy"和20。
如果你嫌这种方法有一种封装性不良的感觉。来一个对象字面量方式创建对象。
var sutdent = {
name : "easy",
age : 20
};
这样看起来似乎就完美了。但是马上我们就会发现一个十分尖锐的问题:当我们要创建同类的student1,student2,…,studentn时,我们不得不将以上的代码重复n次....
创建多个变量的困扰
有个问题?能不能像工厂车间那样,有一个车床就不断生产出对象呢?我们看”工厂模式”。
工厂模式创建对象
JS中没有类的概念,那么我们不妨就使用一种函数将以上对象创建过程封装起来以便于重复调用,同时可以给出特定接口来初始化对象
复制代码
function createStudent(name, age) {
var obj = new Object();
obj.name = name;
obj.age = age;
return obj;
}
var student1 = createStudent("easy1", 20);
var student2 = createStudent("easy2", 20);
...
var studentn = createStudent("easyn", 20);
复制代码
这样一来我们就可以通过createStudent函数源源不断地”生产”对象了。看起来已经高枕无忧了,但贪婪的人类总有不满足于现状的天性:我们不仅希望”产品”的生产可以像工厂车间一般源源不断,我们还想知道生产的产品究竟是哪一种类型的。
比如说,我们同时又定义了”生产”水果对象的createFruit()函数:
水果对象
对于以上代码创建的对象v1、v2,我们用instanceof操作符去检测,他们统统都是Object类型。我们的当然不满足于此,我们希望v1是Student类型的,而v2是Fruit类型的。为了实现这个目标,我们可以用自定义构造函数的方法来创建对象
构造函数模式创建对象
在上面创建Object这样的原生对象的时候,我们就使用过其构造函数:
var obj = new Object();
构造函数创建原生数组
在进行自定义构造函数创建对象之前,我们首先了解一下构造函数和普通函数有什么区别。
1、实际上并不存在创建构造函数的特殊语法,其与普通函数唯一的区别在于调用方法。对于任意函数,使用new操作符调用,那么它就是构造函数;不使用new操作符调用,那么它就是普通函数。
2、按照惯例,我们约定构造函数名以大写字母开头,普通函数以小写字母开头,这样有利于显性区分二者。例如上面的new Array(),new Object()。
3、使用new操作符调用构造函数时,会经历(1)创建一个新对象;(2)将构造函数作用域赋给新对象(使this指向该新对象);(3)执行构造函数代码;(4)返回新对象;4个阶段。
ok,了解了构造函数和普通函数的区别之后,我们使用构造函数将工厂模式的函数重写,并添加一个方法属性:
复制代码
function Student(name, age) {
this.name = name;
this.age = age;
this.alertName = function(){
alert(this.name)
};
}
function Fruit(name, color) {
this.name = name;
this.color = color;
this.alertName = function(){
alert(this.name)
};
}
复制代码
这样我们再分别创建Student和Fruit的对象:
var v1 = new Student("easy", 20);
var v2 = new Fruit("apple", "green");
instanceof操作符来检测对象类型
这样我们就解决了工厂模式无法区分对象类型的尴尬。那么使用构造方法来创建对象是否已经完美了呢?使用构造器函数通常在js中我们来创建对象。
我们会发现Student和Fruit对象中共有同样的方法,当我们进行调用的时候这无疑是内存的消耗。
我们完全可以在执行该函数的时候再这样做,办法是将对象方法移到构造函数外部:
复制代码
function Student(name, age) {
this.name = name;
this.age = age;
this.alertName = alertName;
}
function alertName() {
alert(this.name);
}
var stu1 = new Student("easy1", 20);
var stu2 = new Student("easy2", 20);
复制代码
在调用stu1.alertName()时,this对象才被绑定到stu1上。
我们通过将alertName()函数定义为全局函数,这样对象中的alertName属性则被设置为指向该全局函数的指针。由此stu1和stu2共享了该全局函数,解决了内存浪费的问题
但是,通过全局函数的方式解决对象内部共享的问题,终究不像一个好的解决方法。如果这样定义的全局函数多了,我们想要将自定义对象封装的初衷便几乎无法实现了。更好的方案是通过原型对象模式来解决。
原型的模式创建对象
原型链甚至原型继承,是整个JS中最难的一部分也是最不好理解的一部分,在这里由于我们课程定位的原因,如果对js有兴趣的同学,可以去查阅一下相关JS原型的一些知识点。更加有助于你以后前端JS的面试。
示例