什么是解释型?什么是编译型?
一位新人,要经历怎样的成长,才能站在技术之巅?
基于HTML5的手机APP
在Web世界里,只有JavaScript能跨平台、跨浏览器驱动网页,与用户交互。
新兴的Node.js把JavaScript引入到了服务器端,JavaScript已经变成了全能型选手。
JavaScript代码可以直接嵌在网页的任何地方,不过通常我们都把JavaScript代码放到<head>中:
<head>
<script>
alert('Hello, world');
</script>
</head>
<script>包含的代码将直接被浏览器执行
第二种方法是把JavaScript代码放到一个单独的.js文件,然后在HTML中通过<script src="..."></script>引入这个文件:
<head>
<script src="/static/js/abc.js"></script>
</head>
把JavaScript代码放入一个单独的.js文件中更利于维护代码,并且多个页面可以各自引用同一份.js文件。
俗话说得好,“工欲善其事,必先利其器。”,写JavaScript的时候,如果期望显示ABC,结果却显示XYZ,到底代码哪里出了问题?不要抓狂,也不要泄气,作为小白,要坚信:JavaScript本身没有问题,浏览器执行也没有问题,有问题的一定是我的代码。
然后就需要你去一步一步的调试了
//打开一个网页,进入开发者工具模式
先点击“控制台(Console)“,在这个面板里可以直接输入JavaScript代码,按回车后执行。
要查看一个变量的内容,在Console中输入console.log(a);,回车后显示的值就是变量的内容。
关闭Console请点击右上角的“×”按钮。请熟练掌握Console的使用方法,在编写JavaScript代码时,经常需要在Console运行测试代码。
如果你对自己还有更高的要求,可以研究开发者工具的“源码(Sources)”,掌握断点、单步执行等高级调试技巧
//断点 单步执行
//单行注释 /* */ 多行注释
Number: NaN:not a number 0/0 Infinity: 无限大 2/0
字符串
布尔值
null
undefined
数组:这个数组和java中的有点不一样,java中的数组是表示一组相同数据类型的值,而js中的数组可以存放不同数据类型的值
var arr = [1, 2, 3.14, 'Hello', null, true];
对象:JavaScript的对象是一组由键-值组成的无序集合
var person = {
name: 'Bob',
age: 20,
tags: ['js', 'web', 'mobile'],
city: 'Beijing',
hasCar: true,
zipcode: null
};
键为对象的属性,调用的话,person.name 对象.属性名
//大多数情况下,我们都应该用null。undefined仅仅在判断函数参数是否传递的情况下有用。
//NaN这个数和任何数都不相等,包括他自己,所有只有一个方法来判断这个值,就是isNaN()
变量:
英文、数字、$和_的组合,且不能用数字开头
这种变量本身类型不固定的语言称之为动态语言,也叫弱语言,与之对应的是静态语言。静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。例如Java是静态语言
和静态语言相比,动态语言更灵活
/* 如果一个变量没有通过var申明就被使用,那么该变量就自动被申明为全局变量
* 在同一个页面不同的js文件中,如果有相同的全局变量名,则会造成不可调试的严重错误,
* 为了修补JavaScript这一严重设计缺陷,ECMA在后续规范中推出了strict模式,在strict模式下运行的JavaScript代码,强制通过var申明变量,未使用var申明变量就使用的,将导致运行错误。
* 启用strict模式的方法是在JavaScript代码的第一行写上:
* 'use strict';
* 这是一个字符串,不支持strict模式的浏览器会把它当做一个字符串语句执行,支持strict模式的浏览器将开启strict模式运行JavaScript。
*/
使用var申明的变量则不是全局变量
字符串:
由于多行字符串用\n写起来比较费事,所以最新的ES6标准新增了一种多行字符串的表示方法,用反引号 ` ... ` 表示:
反引号在键盘的ESC下方,数字键1的左边:
alert(`一
二
三`);
连接字符串+
还有一种方法可以连接字符串,用模板字符串,如果浏览器支持ES6标准,那么可以用模板字符串来替代+
例:var name="小明"; var age=20; var message="你好,"+name+",年龄 "+age;
var name="小明"; var age=20; var message=`你好,${name},年龄 ${age}`;
注意:模板字符串要用反引号
特别注意:字符串是不可变的,如果对字符串的某个索引赋值,不会有任何错误,但是,也没有任何效果
例:var test="Test";
test[0]="x";
alert(test);//结果依然为Test
一些常用的对字符串的操作方法:
indexOf():搜索指定字符串出现的位置
var s="Hello world"; console.log(s.length); s.indexOf("world");//找到了,返回索引的位置,从0开始
s.indexOf("Word"); //没有找到,返回-1
substring():返回指定索引区的子串
var s="Hello world"; s.substring(0,7);//返回Hello w 不包含7 s.substring(5);//从5到最后
数组:
注意:直接给Array的length赋一个新的值会导致Array大小的变化:
例:var arr=[1,2,3]; arr.length=6;//arr=[1,2,3,undefined,undefined,undefined]
数组的方法:
indexOf();//和字符串一样的
slice()就是对应String的substring()版本,它截取Array的部分元素,然后返回一个新的Array:
例: var arr=['a','b','c','d','e','f','g']; var arr1=arr.slice(0,3); var arr2=arr.slice(5);
如果不给slice()传参数,则相当于复制一个数组
push()和pop(): 前者向数组尾部添加若干元素,后者删掉数组最后一个元素
例:var arr=[1,2]; arr.push('a','b');//arr=[1,2,'a','b'] arr.pop();//arr=[1]
unshift()和shift():前者向数组头部添加若干元素,后者删掉数组第一个元素
sort():排序
reverse():反转
splice():splice()方法是修改Array的“万能方法”,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素:
例:var arr=[1,2,3,4,5];
arr.splice(2,2,7,8);//从索引2开始删除2个元素,然后添加7和8两个元素,结果返回被删除的元素3,4
arr.splice(2,2);//从索引2开始删除2个元素,不添加元素
arr.splice(2,0,7,8);不删除,只添加,返回[]
concat():连接两个数组,返回一个新数组,以前的数组并没有被修改
join():join()方法是一个非常实用的方法,它把当前Array的每个元素都用指定的字符串连接起来,然后返回连接后的字符串:
例:var arr=['a','c','v',1,2,3]; arr.join("-"); //a-c-v-1-2-3 如果Array的元素不是字符串,将自动转换为字符串后再连接
对象:
var xiaohong={
name:'小红',
'middle-school':'No 1 middle school' //像这种不是一个有效的变量就要用引号引起来,
} //调用的时候直接用 xiaohong['middle-school'] name也可以用xiaohong['name']来调用,但是能用xiaohong.name 就用这种
检查一个属性是否属于该对象,可以用in 操作符
'name' in xiaohong;//true
'toString' in xiaohong;//true 因为所有的对象都有一个父类object,要想判断是否属于自身的,而不是继承的,用hasOwnProperty();
xiaohong.haoOwnProperty('name');//true
xiaohong.hasOwnProperty('toString');//false
备注:JavaScript把null、undefined、0、NaN和空字符串''视为false,其他值一概视为true,因此上述代码条件判断的结果是true。
prompt('请输入你的姓名:'); //prompt()是一个输入框
for循环:
for循环的一个变体是for ... in循环,它可以把一个对象的所有属性依次循环出来:
例:var o={name:'小明',age:20}; for(var key in o){console.log(key);}
如果要过滤掉对象继承的属性,用hasOwnProperty() if(o.hasOwnProperty(key)){console.log(key);}
Map和Set:
ES6最新引进的新的数据类型
Map是一组键值对的结构,具有极快的查找速度。
初始化Map需要一个二维数组,或者直接初始化一个空Map
var m=new Map(); 或者 var m=new Map([['admin',100],['user',90],['customer',91]]);
m.get('admin');//100 m.set('a',80); //添加一个新的键值对 m.has('admin');//判断是否有这个键 m.delete('admin');//删除
Set和Map类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set中,没有重复的key。
要创建一个Set,需要提供一个Array作为输入,或者直接创建一个空Set
var s=new Set(); 或者 var s=new Set([1,2,3]);
s.add(4);//添加新元素 s.delete(1);//删除
iterable:
遍历Array可以采用下标循环,遍历Map和Set就无法使用下标。为了统一集合类型,ES6标准引入了新的iterable类型,Array、Map和Set都属于iterable类型。
具有iterable类型的集合可以通过新的for ... of循环来遍历。
函数:
注意:如果没有return语句,函数执行完毕后也会返回结果,只是结果为undefined
JavaScript还有一个免费赠送的关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数
function foo(x) { alert(x); // 10
for (var i=0; i<arguments.length; i++) {
alert(arguments[i]); // 10, 20, 30
}
}
foo(10, 20, 30);
利用arguments,你可以获得调用者传入的所有参数,也就是说,即使函数不定义任何参数,还是可以拿到参数的值:
JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:
注意:只提升申明,不提升赋值
javascript默认有一个全局对象window,全局作用域的变量实际上会被绑定到window上,作为window的一个属性,window.property
常量:通常用大写字母表示,并且值是不能更改的
const PI=3.14;
var y=new Date();//获取时间 var y=new Date().getFullYear();//获得日期的年
为了解决this的指向问题,可以在方法中用一个that先捕获this,然后在方法中就可以继续定义其他函数了 var that=this;
apply() 和call()函数 ,apply()函数两个参数,第一个参数为this指向的对象,第二个参数为arrry数组 call()函数第二个参数穿的数不是数组,按顺序传入
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
getAge.apply(xiaoming,[]);//传xiaoming这个对象进去,替代方法中的this,就不会出错了
高阶函数:
函数方法中传入函数
例如Array数组的map()方法
var arr=[1,2,3,4,5,6];
arr.map(String);//直接把数组中的元素全部转换为字符串['1','2','3','4','5','6']
也可传入自己定义的方法; function pow(x){return x*x;}; arr.map(pow);
Array的reduce()方法
var arr=[1,2,3,4,5]; arr.reduce(function(x,y){return x+y});//求和,reduce方法中传的function必须接收两个参数
var arr=[1,2,3,4,5]; arr.reduce(function(x,y){return x*10+7}); //把数组变成12345;
filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素。
和map()类似,Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
sort():
Array的sort()方法默认把所有元素先转换为String再排序,结果'10'排在了'2'的前面,因为字符'1'比字符'2'的ASCII码小
可以在sort()方法中传入一个自定义的比较函数来根据自己的想法排序
var arr=[1,19,2,21]; arr.sort(function(x,y){if(x<y) return -1; if(x>y) return 1; if(x==y) return 0});
闭包:
当一个函数返回另一个函数,就是返回值为一个函数
返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
箭头函数:
就相当于一种匿名函数
x => x*x; 等价于 function (x){return x*x;}
一位新人,要经历怎样的成长,才能站在技术之巅?
基于HTML5的手机APP
在Web世界里,只有JavaScript能跨平台、跨浏览器驱动网页,与用户交互。
新兴的Node.js把JavaScript引入到了服务器端,JavaScript已经变成了全能型选手。
JavaScript代码可以直接嵌在网页的任何地方,不过通常我们都把JavaScript代码放到<head>中:
<head>
<script>
alert('Hello, world');
</script>
</head>
<script>包含的代码将直接被浏览器执行
第二种方法是把JavaScript代码放到一个单独的.js文件,然后在HTML中通过<script src="..."></script>引入这个文件:
<head>
<script src="/static/js/abc.js"></script>
</head>
把JavaScript代码放入一个单独的.js文件中更利于维护代码,并且多个页面可以各自引用同一份.js文件。
俗话说得好,“工欲善其事,必先利其器。”,写JavaScript的时候,如果期望显示ABC,结果却显示XYZ,到底代码哪里出了问题?不要抓狂,也不要泄气,作为小白,要坚信:JavaScript本身没有问题,浏览器执行也没有问题,有问题的一定是我的代码。
然后就需要你去一步一步的调试了
//打开一个网页,进入开发者工具模式
先点击“控制台(Console)“,在这个面板里可以直接输入JavaScript代码,按回车后执行。
要查看一个变量的内容,在Console中输入console.log(a);,回车后显示的值就是变量的内容。
关闭Console请点击右上角的“×”按钮。请熟练掌握Console的使用方法,在编写JavaScript代码时,经常需要在Console运行测试代码。
如果你对自己还有更高的要求,可以研究开发者工具的“源码(Sources)”,掌握断点、单步执行等高级调试技巧
//断点 单步执行
//单行注释 /* */ 多行注释
Number: NaN:not a number 0/0 Infinity: 无限大 2/0
字符串
布尔值
null
undefined
数组:这个数组和java中的有点不一样,java中的数组是表示一组相同数据类型的值,而js中的数组可以存放不同数据类型的值
var arr = [1, 2, 3.14, 'Hello', null, true];
对象:JavaScript的对象是一组由键-值组成的无序集合
var person = {
name: 'Bob',
age: 20,
tags: ['js', 'web', 'mobile'],
city: 'Beijing',
hasCar: true,
zipcode: null
};
键为对象的属性,调用的话,person.name 对象.属性名
//大多数情况下,我们都应该用null。undefined仅仅在判断函数参数是否传递的情况下有用。
//NaN这个数和任何数都不相等,包括他自己,所有只有一个方法来判断这个值,就是isNaN()
变量:
英文、数字、$和_的组合,且不能用数字开头
这种变量本身类型不固定的语言称之为动态语言,也叫弱语言,与之对应的是静态语言。静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。例如Java是静态语言
和静态语言相比,动态语言更灵活
/* 如果一个变量没有通过var申明就被使用,那么该变量就自动被申明为全局变量
* 在同一个页面不同的js文件中,如果有相同的全局变量名,则会造成不可调试的严重错误,
* 为了修补JavaScript这一严重设计缺陷,ECMA在后续规范中推出了strict模式,在strict模式下运行的JavaScript代码,强制通过var申明变量,未使用var申明变量就使用的,将导致运行错误。
* 启用strict模式的方法是在JavaScript代码的第一行写上:
* 'use strict';
* 这是一个字符串,不支持strict模式的浏览器会把它当做一个字符串语句执行,支持strict模式的浏览器将开启strict模式运行JavaScript。
*/
使用var申明的变量则不是全局变量
字符串:
由于多行字符串用\n写起来比较费事,所以最新的ES6标准新增了一种多行字符串的表示方法,用反引号 ` ... ` 表示:
反引号在键盘的ESC下方,数字键1的左边:
alert(`一
二
三`);
连接字符串+
还有一种方法可以连接字符串,用模板字符串,如果浏览器支持ES6标准,那么可以用模板字符串来替代+
例:var name="小明"; var age=20; var message="你好,"+name+",年龄 "+age;
var name="小明"; var age=20; var message=`你好,${name},年龄 ${age}`;
注意:模板字符串要用反引号
特别注意:字符串是不可变的,如果对字符串的某个索引赋值,不会有任何错误,但是,也没有任何效果
例:var test="Test";
test[0]="x";
alert(test);//结果依然为Test
一些常用的对字符串的操作方法:
indexOf():搜索指定字符串出现的位置
var s="Hello world"; console.log(s.length); s.indexOf("world");//找到了,返回索引的位置,从0开始
s.indexOf("Word"); //没有找到,返回-1
substring():返回指定索引区的子串
var s="Hello world"; s.substring(0,7);//返回Hello w 不包含7 s.substring(5);//从5到最后
数组:
注意:直接给Array的length赋一个新的值会导致Array大小的变化:
例:var arr=[1,2,3]; arr.length=6;//arr=[1,2,3,undefined,undefined,undefined]
数组的方法:
indexOf();//和字符串一样的
slice()就是对应String的substring()版本,它截取Array的部分元素,然后返回一个新的Array:
例: var arr=['a','b','c','d','e','f','g']; var arr1=arr.slice(0,3); var arr2=arr.slice(5);
如果不给slice()传参数,则相当于复制一个数组
push()和pop(): 前者向数组尾部添加若干元素,后者删掉数组最后一个元素
例:var arr=[1,2]; arr.push('a','b');//arr=[1,2,'a','b'] arr.pop();//arr=[1]
unshift()和shift():前者向数组头部添加若干元素,后者删掉数组第一个元素
sort():排序
reverse():反转
splice():splice()方法是修改Array的“万能方法”,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素:
例:var arr=[1,2,3,4,5];
arr.splice(2,2,7,8);//从索引2开始删除2个元素,然后添加7和8两个元素,结果返回被删除的元素3,4
arr.splice(2,2);//从索引2开始删除2个元素,不添加元素
arr.splice(2,0,7,8);不删除,只添加,返回[]
concat():连接两个数组,返回一个新数组,以前的数组并没有被修改
join():join()方法是一个非常实用的方法,它把当前Array的每个元素都用指定的字符串连接起来,然后返回连接后的字符串:
例:var arr=['a','c','v',1,2,3]; arr.join("-"); //a-c-v-1-2-3 如果Array的元素不是字符串,将自动转换为字符串后再连接
对象:
var xiaohong={
name:'小红',
'middle-school':'No 1 middle school' //像这种不是一个有效的变量就要用引号引起来,
} //调用的时候直接用 xiaohong['middle-school'] name也可以用xiaohong['name']来调用,但是能用xiaohong.name 就用这种
检查一个属性是否属于该对象,可以用in 操作符
'name' in xiaohong;//true
'toString' in xiaohong;//true 因为所有的对象都有一个父类object,要想判断是否属于自身的,而不是继承的,用hasOwnProperty();
xiaohong.haoOwnProperty('name');//true
xiaohong.hasOwnProperty('toString');//false
备注:JavaScript把null、undefined、0、NaN和空字符串''视为false,其他值一概视为true,因此上述代码条件判断的结果是true。
prompt('请输入你的姓名:'); //prompt()是一个输入框
for循环:
for循环的一个变体是for ... in循环,它可以把一个对象的所有属性依次循环出来:
例:var o={name:'小明',age:20}; for(var key in o){console.log(key);}
如果要过滤掉对象继承的属性,用hasOwnProperty() if(o.hasOwnProperty(key)){console.log(key);}
Map和Set:
ES6最新引进的新的数据类型
Map是一组键值对的结构,具有极快的查找速度。
初始化Map需要一个二维数组,或者直接初始化一个空Map
var m=new Map(); 或者 var m=new Map([['admin',100],['user',90],['customer',91]]);
m.get('admin');//100 m.set('a',80); //添加一个新的键值对 m.has('admin');//判断是否有这个键 m.delete('admin');//删除
Set和Map类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set中,没有重复的key。
要创建一个Set,需要提供一个Array作为输入,或者直接创建一个空Set
var s=new Set(); 或者 var s=new Set([1,2,3]);
s.add(4);//添加新元素 s.delete(1);//删除
iterable:
遍历Array可以采用下标循环,遍历Map和Set就无法使用下标。为了统一集合类型,ES6标准引入了新的iterable类型,Array、Map和Set都属于iterable类型。
具有iterable类型的集合可以通过新的for ... of循环来遍历。
函数:
注意:如果没有return语句,函数执行完毕后也会返回结果,只是结果为undefined
JavaScript还有一个免费赠送的关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数
function foo(x) { alert(x); // 10
for (var i=0; i<arguments.length; i++) {
alert(arguments[i]); // 10, 20, 30
}
}
foo(10, 20, 30);
利用arguments,你可以获得调用者传入的所有参数,也就是说,即使函数不定义任何参数,还是可以拿到参数的值:
JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:
注意:只提升申明,不提升赋值
javascript默认有一个全局对象window,全局作用域的变量实际上会被绑定到window上,作为window的一个属性,window.property
常量:通常用大写字母表示,并且值是不能更改的
const PI=3.14;
var y=new Date();//获取时间 var y=new Date().getFullYear();//获得日期的年
为了解决this的指向问题,可以在方法中用一个that先捕获this,然后在方法中就可以继续定义其他函数了 var that=this;
apply() 和call()函数 ,apply()函数两个参数,第一个参数为this指向的对象,第二个参数为arrry数组 call()函数第二个参数穿的数不是数组,按顺序传入
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
getAge.apply(xiaoming,[]);//传xiaoming这个对象进去,替代方法中的this,就不会出错了
高阶函数:
函数方法中传入函数
例如Array数组的map()方法
var arr=[1,2,3,4,5,6];
arr.map(String);//直接把数组中的元素全部转换为字符串['1','2','3','4','5','6']
也可传入自己定义的方法; function pow(x){return x*x;}; arr.map(pow);
Array的reduce()方法
var arr=[1,2,3,4,5]; arr.reduce(function(x,y){return x+y});//求和,reduce方法中传的function必须接收两个参数
var arr=[1,2,3,4,5]; arr.reduce(function(x,y){return x*10+7}); //把数组变成12345;
filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素。
和map()类似,Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
sort():
Array的sort()方法默认把所有元素先转换为String再排序,结果'10'排在了'2'的前面,因为字符'1'比字符'2'的ASCII码小
可以在sort()方法中传入一个自定义的比较函数来根据自己的想法排序
var arr=[1,19,2,21]; arr.sort(function(x,y){if(x<y) return -1; if(x>y) return 1; if(x==y) return 0});
闭包:
当一个函数返回另一个函数,就是返回值为一个函数
返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
箭头函数:
就相当于一种匿名函数
x => x*x; 等价于 function (x){return x*x;}