初始JavaScript(一)
什么是JavaScript
JavaScript是一门世界上最流行的脚本语言
历史
34岁的系统程序员Brendan Eich在1995年4月,网景公司录用了他。
Brendan Eich的主要方向和兴趣是函数式编程,网景公司招聘他的目的,是研究将Scheme语言作为网页脚本语言的可能性。Brendan Eich本人也是这样想的,以为进入新公司后,会主要与Scheme语言打交道。
但是网景公司在他入职仅仅一个月之后希望开发一款与Java相似,但是比Java简单,使得非专业的网页作者也能很快上手的"简化版Java语言",因此Brendan Eich被指定为这种"简化版Java语言"的设计师.
但是,他对Java一点兴趣也没有。为了应付公司安排的任务,他只用10天时间就把Javascript设计出来了。
由于设计时间太短,语言的一些细节考虑得不够严谨,导致后来很长一段时间,Javascript写出来的程序混乱不堪。
它的设计思路是:
(1)借鉴C语言的基本语法;
(2)借鉴Java语言的数据类型和内存管理;
(3)借鉴Scheme语言,将函数提升到"第一等公民"(first class)的地位;
(4)借鉴Self语言,使用基于原型(prototype)的继承机制。
所以,Javascript语言实际上是两种语言风格的混合产物----(简化的)函数式编程+(简化的)面向对象编程。这是由Brendan Eich(函数式编程)与网景公司(面向对象编程)共同决定的。
多年以后,Brendan Eich还是看不起Java.....
ECMAScript可以理解为是JavaScript的一个标准
最新版本已经到es6.
但是大部分浏览器还只停留在支持es5代码上.
入门
引入JavaScript
内部标签
<script>
alart("hello world")
</script>
外部引入
abs.js
//....
test.js
//....
<script src="abs.js">
</script>
基本语法入门
//定义变量
var score = 75;
//条件控制
if(score>60){
alart("aaa")
}else if{
//xxx....
}else{
//xxx....
}
//console.log(score) 在浏览器的控制台打印变量
数据类型
数值,文本,图形,音频,视频.....
变量
//不要以数字开头
var xxx
let xxx
//严格检查模式
'use strict';
var和let的区别
在ES6之前,我们都是用var来声明变量,而且JS只有函数作用域和全局作用域,没有块级作用域,所以{}限定不了var声明变量的访问范围。
例如:
{
var i = 9;
}
console.log(i); // 9
ES6新增的let,可以声明块级作用域的变量。
{
let i = 9; // i变量只在 花括号内有效!!!
}
console.log(i); // Uncaught ReferenceError: i is not defined
let没有变量提升与暂时性死区
用let声明的变量,不存在变量提升。而且要求必须 等let声明语句执行完之后,变量才能使用,不然会报Uncaught ReferenceError错误。
例如:
console.log(aicoder); // 错误:Uncaught ReferenceError ...
let aicoder = 'aicoder.com';
// 这里就可以安全使用aicoder
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
let变量不能重复声明
let不允许在相同作用域内,重复声明同一个变量。否则报错:Uncaught SyntaxError: Identifier 'XXX' has already been declared
例如:
let a = 0;
let a = 'sss';
// Uncaught SyntaxError: Identifier 'a' has already been declared
总结
局部变量建议都使用let去定义.
'use strict'建议都写在script的第一行.
number
js不区分小数和整数,Number
123 //整数
123.1 //浮点数123.1
1.123e3 //科学计数法
-99 //负数
NaN //not a number
Infinity //无限大
字符串
'abc'
"abc"
布尔值
true
false
逻辑运算
&&
||
!
比较运算符!!!
=
== 等于(类型不一样,值一样也会判断为true)
=== 绝对等于(类型一样,值一样,结果true)
Js的缺陷 ,建议用===比较
须知:
- NaN===NaN,这个表达式得false
- NaN比较要用isNaN(NaN)
浮点数问题:
console.log(1/3)===(1-2/3)
<false
尽量避免使用浮点数运算,存在精度问题.
null和undifine
- null 空
- undifined未定义
数组
//数组用[]
var arr = [1,2,'hello',null,true]
对象
//对象用{}
//每个属性之间用','隔开
var person={
name: "LongDa",
age: "12",
tags: ['js','java','mysql']
}
>person.name
<"LongDa"
数据类型
字符串
1 通常字符串我们使用 "" , '' 包裹
2 打印字符 要转义
\'
\n
\t
\u4e2d \u#### Unicode字符
//<中
\x41 Ascll字符
3 多行字符串编写
// `
let msg =
`hello
world
你好`;
4 模板字符串
let name='longda';
let age=12;
let msg='hello,${name}'
5 字符串长度
str.length
6 字符串不可变
7 大小写转换
//这里是方法,不是属性
student.toUpperCase()
student.toLowerCase()
8 substring
[)
student.substring(1) //从第一个字符串截取到最后一个字符串
student.substring(1,3) //[1,3)
数组
Array可以包含任意的数据类型
var arr=[1,2,3,4,5]
arr[0]
<1
1 长度
arr.length
注意:假如给arr.length赋值,数组大小就会发生变化,如果赋值过小,元素就会丢失
2 indexof(),通过元素获得下标索引
arr.indexof(2)
<1
注意:字符串的"1"和数字1是不同的
3 slice() 截取Array的一部分,返回一个新数组
类似于string中的substring
4 push,pop尾部
//类似于栈中的push,pop
push: 入栈
pop: 出栈
5 unshift(),shift()头部
unshift: 从头部入栈
shift: 从头部出栈
6 sort()
>(3) ["c","b","a"]
>arr.sort()
<(3) ["a","b","c"]
7 reverse()
>(3) ["a","b","c"]
>arr.sort()
<(3) ["c","b","a"]
8 concat()
>(3) ["a","b","c"]
>arr.concat([1,2,3])
<(6) ["a","b","c",1,2,3]
>arr
<(3) ["a","b","c"]
注意: concat()并没有修改数组,只是会返回一个新数组.
9 连接符join
打印拼接数组,使用特定的字符串连接
>(3) ["a","b","c"]
>arr.join('-')
<"a-b-c"
10 多维数组
>arr = [[1,2][3,4],["5","6"]]
>arr[1][1]
<4
对象
js中对象,{....}表示一个对象,键值对描述属性xxxx: xxxx,多个属性之间使用,隔开,最后一个属性不加,
JavaScript中的所有的键都是字符串,值是任意对象.
let 对象名= {
属性名: 属性值,
属性名: 属性值,
属性名: 属性值
}
let person={
name: "LongDa",
age: "12",
tags: ['js','java','mysql']
}
1 对象赋值
>person.name='longda'
<longda
>person.name
<longda
2 使用一个不存在的对象属性,不会报错! undifined
>person.haha
<undifined
3 动态的删除属性,通过delete删除对象的属性
>delete person.name
<true
4 动态的添加,直接给新的属性添加值即可
>person.haha='hah'
<'hah'
5 判断属性值是否在这个对象中! xxx in xxx.
>'age' in person
<true
//继承
>'toString' in person
<true
6 判断一个属性是否是这个对象自身拥有的hasOwnProperty()
>person.hasOwnProperty('toString')
<false
>person.hasOwnProperty('age')
<true
流程控制
if判断 while循环 for循环
Map和Set
map
>var map new Map([['tom',100],['jack',90]]);
>var name = map.get('tom') //通过key获得value
>console.log(name)
>map.set('admin',123456)
set
var set = new Set([3,1,1,1,1])
set.add(2) //添加元素
set.delete(3) //删除元素
遍历map
>var map new Map([['tom',100],['jack',90]]);
for(let x of map){
console.log(x)
}
函数
定义函数
绝对值函数
function abs(x){
if(x>=0){
return x;
}else {
return -x;
}
}
一旦执行到return,代表函数结束,返回结果!
如果没有执行return,函数执行完也会返回结果,结果就是undifined
定义方式二
var abs = function(x){
if(x>=0){
return x;
}else {
return -x;
}
}
function(x){....}这是一个匿名函数,但是可以把结果赋值给abs,通过abs就可以调用函数!
调用函数
abs(10) //10
abs(-10) //10
参数问题:JavaScript可以传任意个参数,也可以不传递参数.
假设不存在参数,如何规避?
var abs = function(){
//手动抛出来判断异常
if(typeof x !== 'Number'){
throw 'Not a Number'
}
if(x>=0){
return x;
}else {
return -x;
}
}
arguments
arguments是一个js免费赠送的关键词;
代表,传递进来的所有的参数,是一个数组.
变量的作用域
在javaScript中,var定义变量实际是有作用域的.
假设在函数体中声明,则在函数体外不可使用~
function ld(){
var x = 1;
x = x + 1;
}
x = x + 2; //Uncaught ReferenceError:x is not defind
如果两个使用了相同的变量名,只要在函数内部,就不冲突.
function ld(){
var x = 1;
x = x + 1;
}
function ld2(){
var x = ''a';
x = x + 1;
}
内部函数可以访问外部函数的成员,反之则不行
function ld(){
var x = 1;
function ld2(){
var y = x + 1;
}
var z = y + 1; //Uncaught ReferenceError:x is not defind
}
假设,内部函数变量和外部函数的变量,重名
function ld(){
var x = 1;
function ld2(){
var x = 'A';
console.log('inner' + x)
}
console.log('outer'+x) ;
ld2();
}
<outer1
<innerA
简单来说,函数查找变量从自身函数开始~,遵循就近原则,由内向外查找,假设外部存在这个同名的函数变量,则自动屏蔽外部函数变量.
提升变量的作用域
function ld2(){
var x = ''a' + y;
console.log(x);
var y = 'y';
}
<xundefined
注意:js执行引擎,会自动提升y的声明,但是不会提升变量y的赋值.
因此,要养成规范,所有的变量定义都放在函数的头部,不要乱放,便于代码维护.
即,先声明,后定义,再调用.
全局变量
x=1;
function f(){
console.log(x);
}
f();
console.log(x);
<1
<1
全局对象window
var = 'xxx';
alert(x);
alert(window.x);
JavaScript 实际上只有一个全局作用域,任何变量(函数也可以视为变量),假设没有在函数作用范围内找到,就会向外查找,如果在全局作用域都没有找到,报错RefrenceError
规范
[由于我们所有的全局变量都会绑定到我们的window上,如果不同的js文件,使用了相同的全局变量,会发生冲突.
如何解决?
//唯一全局变量
var longda = {}
//定义全局变量
longda.name='luolongda'
longda.add=function(a,b){
return a+b;
}
把自己的代码全部放入自己定义的唯一空间名字中,降低全局命名冲突的问题~
例如:jQuery
局部作用域let
function aaa(){
for(var i = 0; i<100;i++){
console.log(i)
}
console.log(i+1);
}
<0
<1
.
.
.
<100
<101 //i出了for循环的作用域
ES6中,let关键字解决了局部作用域冲突
function aaa(){
for(let i = 0; i<100;i++){
console.log(i)
}
console.log(i+1);
}
<Uncaught ReferenceError:i is not defind
建议使用let去定义局部作用域的变量.
const 常量
在ES6之前,定义常量的方法是:只有全部大写字母命名的变量就是常量...,非常随意
var PI = '3.14'
在ES6引入了常量关键字const
const PI = '3.14';
PI = '123' //这时再修改就会报错
方法
定义方法
方法就是把函数放在对象的里面,对象只有两个东西,属性和方法.
var longda = {
name: '龙达',
birth: 2020,
age: function(){
let now = new Date().getFullYear();
return now-this.birth;
//this指向方法调用的对象
}
}
longda.name
//方法调用一定要带()
longda.age()
apply
在js中可以控制this指向
function getAge(){
let now = new Date().getFullYear();
return now-this.birth;
}
var longda = {
name: '龙达',
birth: 2020,
age: getAge
}
}
getAge.apply(longda,[]);
//this指向了longda,参数为空
内部对象
Date
var now = new Date();
console.log(now);
<当前时间
now.getFullYear();
now.getMonth();
now.getDate(); //日期
now.getDay(); //星期x
now.getHours();
now.gettime(); //时间戳,从1970.1.1 0:00:00开始至今
转换
now = new Date(1578061982765);
Sat Jan 04 2020 10:49:35 GMT+0800(中国标准时间)
now.toLocaleString()
"2020/1/4 上午10:49:35"

关于JavaScript....
浙公网安备 33010602011771号