初始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"
posted @ 2020-08-05 21:50  longda666  阅读(79)  评论(0)    收藏  举报