menu DNXRZL的故事
search self_improvement
目录

javascript学习笔记

DNXRZL
DNXRZL 2021年07月08日  ·  阅读 344

小说

type="text/javascript"

这个属性的含义是告诉浏览器这是个js语言,因为在早期客户端的脚本语言可能不只有Js.不过现在不需要写了,现在的浏览器都支持Js语言了。

js构成

231048969.jpg

分号 ;

分号用于分隔 JavaScript 语句。

通常我们在每条可执行的语句结尾添加分号。

使用分号的另一用处是在一行中编写多条语句

var s;
var d='sf';

输出的一些小注意

var a=123,b='we';
console.log(a,b) //这个函数可以像python一样连写多个变量
结果:123 "we"
var a=123,b='we';
alert(a,b) //这个函数只能接受一个变量
结果:123

对代码行进行折行

您可以在文本字符串中使用反斜杠对代码行进行换行。下面的例子会正确地显示:

实例

document.write("你好 \ 
世界!");

不过,您不能像这样折行:

document.write \ 
("你好世界!");

var let const的区别-待完善Ing

var

如果使用关键字 var 声明一个变量,那么这个变量就属于当前的函数作用域,如果声明是发生在任何函数外的顶层声明,那么这个变量就属于全局作用域。举例说明:


var a = 1; //此处声明的变量a为全局变量
function foo(){
   var a = 2;//此处声明的变量a为函数foo的局部变量
   console.log(a);//2
}
foo();
console.log(a);//1

如果在声明变量时,省略 var 的话,该变量就会变成全局变量,如果全局作用域中存在该变量,就会更新其值。如:

var a = 1; //此处声明的变量a为全局变量
function foo(){
   a = 2;//此处的变量a也是全局变量
   console.log(a);//2
}
foo();
console.log(a);//2

var 声明的变量存在提升(hoisting)。

console.log(a);//此时a已被申明,但没有赋值undefined
var a = 1;

let

  1. let 声明的变量具有块作用域的特征。
  2. 在同一个块级作用域,不能重复声明变量。
  3. let 声明的变量不存在变量提升,换一种说法,就是 let 声明存在暂时性死区(TDZ)。
let a = 1;
console.log(a);//1
console.log(b);//Uncaught ReferenceError: b is not defined
let b = 2;
function foo(){
    let a = 1;
    let a = 2;//Uncaught SyntaxError: Identifier 'a' has already been declared
}

const

const 声明方式,除了具有 let 的上述特点外,其还具备一个特点,即 const 定义的变量,一旦定义后,就不能修改,即 const 声明的为常量。

const a = 1;
console.log(a);//1
a = 2;
console.log(a);//Uncaught TypeError: Assignment to constant variable.

但是,并不是说 const 声明的变量其内部内容不可变,如:

const obj = {a:1,b:2};
console.log(obj.a);//1
obj.a = 3;
console.log(obj.a);//3

所以准确的说,是 const 声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。

重新声明 JavaScript 变量

如果重新声明 JavaScript 变量,该变量的值不会丢失:

在以下两条语句执行后,变量 a 的值依然是 “Volvo”:

var a="Volvo";
var a;

JavaScript 拥有动态类型

JavaScript 拥有动态类型。这意味着相同的变量可用作不同的类型:

实例

var x;        // x 为 undefined
var x = 5;      // 现在 x 为数字
var x = "John";   // 现在 x 为字符串

数据类型(共两大类-重点)

简单数据类型:Number、string、boolean、undefined、null

复杂数据类型:object

数字类型

进制

在数字前加上‘0’,就表示8进制,如:var a = 010;

加0x表示16进制

数字里的最大大值:

Number.MAX_VALUE
1.7976931348623157e+308

数字里的最小值:

Number.MIN_VALUE
5e-324

三个特殊类型

无穷大:infinity

无穷小:-infinity

不是一个数字:Not a number :NaN

NaN例子:alert(‘pink’-10) 如果:NaN

但是alert(‘pink’+10)就是字符串拼接了,有结果:pink10

判断是不是一个数字函数:isNaN()

是数字返回false,不是数字返回true

值得注意的是:就算是字符串型的数字也是false

字符串类型

js中可以用’‘和"",但最好用’’

字符串嵌套

如:var a=‘你好呀,"今天"天气真不错’ 或 var a=“你好呀,'今天’天气真不错”

转义字符

\n、'、" 这三个比比较常用

其他:\t tab键 \b 空格键

字符串长度属性

string.length
例如:var a = '12345'; a.length

字符串拼接

字符串+任何类型=字符串 如:gh+123=gh123

var c='fg';
c+123
"fg123"

字符串拼接加强版

var a = 123;
console.log('helllo'+ a +'world')
hello123world

boolean布尔型

true就是1

false就是0

true+1
2
false+1
1

undefined和null

只申明一个变量不赋值就是undefined

注意:虽然说字符串和任何数据类型相加都会是字符串,但这个undefined和数字相加例外

var g;
console.log(g+1)
输出:NaN
var g;
console.log(g+'pink')
输出:undefinedpink

null是空值的意思

var a=null;
console.log(a+'pink')
输出:nullpink
console.log(a+1)
输出:1

typeof属性判断数据类型

var s=123;
console.log(typeof s)
输出:number

值得注意的是:在控制台里,黑色颜色的输出结果是字符串,蓝色的是数字

数据类型转换

转换成字符串

3222691141.jpg

var a=123;
console.log(a.toString())
输出:123 字符串
console.log(String(a))
输出:123 字符串

3759419291.jpg

转换成数字型

409653985.jpg

var a='123';
console.log(parseInt(a)) //转换成整数型
输出:123
console.log(parseFloat(a)) //转换成浮点型
输出:123
console.log(Number(a)) //不分
输出:123
Number()转换比较强制性,无论浮点数还是整数都转换且不做其他处理,如下:
var s=12.7
Number(s)
12.7
parseInt(s)
12

隐式转换

只支持运算符:- * /

var j='12';
j-1
输出:11
j*1
输出:12
j/1
输出:12
这样也可以的(两个字符串相减、相乘、相除)
'2'-'3'
输出:-1
当然运算符+是不可以的,他只能拼接
j+1
输出:"121"

转换成布尔值boolean

568186738.jpg

792235801.jpg

注意函数Boolean()函数的首字母要大写

编译性与解释性语言的区别

翻译成机械语言有两种:编译和解释

解释性语言就是翻译一行执行一样

编译性语言就是一次编译完再执行

1292780404.jpg

运算符

算术运算符(和python 差不多)

2195791587.jpg

表达式

含义:由数字、运算符、变量组成的式子

递增与递减

前置递增:++number

含义:执行时直接递增然后返回已增的值

后置递增:number++

含义:执行时会先返回原值再递增,但单独使用时和前置递增一样

var a=4;
console.log(a++ +2)
输出:6
console.log(a)
输出:5

比较运算符

3912189804.jpg

逻辑运算符

1238059098.jpg

短路运算(逻辑中断)

表达式1 && 表达式2

如果表达式1为真,则返回表达式2

如果表达式1为假,则返回表达式1

123 && 345
输出:345
0 && 123
输出:0

当判断第一个表达式时,就中断了,后面的不判断了
0 && 123 +123 && 12
输出:0

表达式1 || 表达式2

如果表达式1为真,则返回表达式1

如果表达式1为假,则返回表达式2

0 || 123 || 234
输出:123

赋值运算符

1952011297.jpg

运算符优先级

1631928363.jpg

分支语句(判断)

642443441.jpg

if语句

if (){

}else{

} //无需写;号

if (){

}else if (){

}else{

}

实例:
var a=parseInt(prompt('请输入数字'))
		if (a==1){
			alert('你真好!');
		}else if (a==3){
			alert('哈哈');
		}else{
			alert('嗯')
		}

switch语句

switch (条件表达式){ //条件表达式返回值一定要和case里的值全等于,即值等于、类型也等于。
     case value:
        ...
        break
     case value:
        ...
        break
     default:
        ...
}

实例:1
var a=parseInt(prompt('请输入'));
		switch(a){
			case 1:
				alert('hello');
				break
			case 2:
				alert('hh');
				break
			default:
				alert('end')
		}
		
实例:2
var a=String(prompt('请输入')); //注意String()
switch(a){
    case '1': //注意这
        alert('hello');
        break
    case 2:
        alert('hh');
        break
    default:
        alert('end')
        }

三元表达式(也可做为if判断来用)

含义,‘元’的意思在数学上是未知数,变量,而三元表达式同样有三个变量或者说是变动的表达式…

结构:条件表达式?表达式1:表达式2

执行思路:如果条件表达式为真,则返回表达式1的值,否则,返回表达式2的值

var a=2;
console.log(a==2?3:4)//三元表达式
输出:3

for 循环

for (初始化变量;条件表达式;操作表达式){
    ...
		}
实例:
for (var i=1;i<=10;i++){ //注意这里变量i要赋值
	console.log('hello')
    }

断点调试-理解for循环的运行过程

给程序打断点来观察程序的运行过程

1566869794.png

while循环

while (条件表达式){
      ...
		}
实例:
var t=1;
while (t<10){ //这里不能定义变量,会报错,须在外定义
    console.log('hello');
	t++
		}

do while循环

特点:首次执行时,不会考虑条件,先把do里边的执行了再说,第二次循环再看while里的条件

var i=1;
do {
	console.log('hellos');
    i++
    } while(i<=10)

数组

和python的列表比较像

创建一个数组有3种方法:

常规方式://比较麻烦吧
var myCars=new Array();
myCars[0]="Saab";      
myCars[1]="Volvo";
myCars[2]="BMW";

简洁方式: //实例对象的方式
var myCars=new Array("Saab","Volvo","BMW");

字面: //很直观的就可以看出来是数组,所以叫字面
var myCars=["Saab","Volvo","BMW"];

访问数组

var myCars=["Saab","Volvo","BMW"];
var k=myCars[0]
console.log(k)
输出:'Saab'

修改数组-请看下面的数组方法

var myCars=["Saab","Volvo","BMW"];
myCars[0]=2;
console.log(myCars)
输出:[2, "Volvo", "BMW"]

数组部分对象方法-重点

concat() //连接两个或多个数组,并返回结果
var hege = ["Cecilie", "Lone"];
var stale = ["Emil", "Tobias", "Linus"];
var kai = ["Robin"];
var children = hege.concat(stale,kai);
输出:["Cecilie", "Lone", "Emil", "Tobias", "Linus", "Robin"]

includes() //判断一个数组是否包含一个特定的元素,必须用let申明
let site = ['runoob', 'google', 'taobao'];
site.includes('runoob'); 

indexOf() //搜索数组中的元素,并返回它所在的位置
var fruits = ["Banana", "Orange", "Apple", "Mango"];
var a = fruits.indexOf("Apple");
输出:2

lastIndexOf() //从数组最后一个开始往前搜索,并返回下标
var fruits = ["Apple", "Orange", "Apple", "Mango"];
var a = fruits.lastIndexOf("Apple");
console.log(a)
输出:2

pop() //删除数组最后一个元素并返回删除的那个元素
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.pop();
输出:Banana,Orange,Apple

push() //向数组的末尾添加一个元素或多个元素并返回数组的长度(下标)
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.push("Kiwi")
输出:Banana,Orange,Apple,Mango,Kiwi

reduce() //将数组里的元素进行计算(从左到右)
var numbers = [65, 44, 12, 4];
function getSum(total, num) {
    return total + num;
}
function myFunction(item) {
    return numbers.reduce(getSum);
}
console.log(myFunction())
输出:125 
自我理解:getSum()函数计算的和返回给reduce()函数,reduce()函数再传参给total,num值不变

reduceRight() //将数组里的元素进行计算(从左到右)
var numbers = [65, 44, 12, 4];
function getSum(total, num) {
    return total + num;
}
function myFunction(item) {
    return numbers.reduceRight(getSum);
}
console.log(myFunction)
输出:125

reverse() //反转数组里的顺序
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.reverse();
输出:Mango,Apple,Orange,Banana

shift() //删除并返回数组里的第一个元素,再说一遍是元素不是下标
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.shift()

sort() //用于对数组的元素进行排序。
排序顺序可以是字母或数字,并按升序或降序。
默认排序顺序为按字母升序。
注意:当数字是按字母顺序排列时"40"将排在"5"前面。
使用数字排序,你必须通过一个函数作为参数来调用。
函数指定数字是按照升序还是降序排列。
注意: 这种方法会改变原始数组!

数字排序(数字和升序):
var points = [40,100,1,5,25,10];
points.sort(function(a,b){return a-b});
结果:1,5,10,25,40,100

数字排序(数字和降序):
var points = [40,100,1,5,25,10];
points.sort(function(a,b){return b-a});
结果:100,40,25,10,5,1

字母默认排序
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();
结果:Apple,Banana,Mango,Orange

数字排序 (字母和降序):
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();
fruits.reverse();
结果:Orange,Mango,Banana,Apple

splice() //添加或删除元素
//语法:array.splice(index,howmany,item1,.....,itemX)
//参数:
index	必需。规定从何处添加/删除元素。
	    该参数是开始插入和(或)删除的数组元素的下标,必须是数字。
howmany	可选。规定应该删除多少元素。必须是数字,但可以是 "0"。
	    如果未规定此参数,则删除从 index 开始到原数组结尾的所有元素。
item1, ..., itemX	可选。要添加到数组的新元素

//添加:
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2,0,"Lemon","Kiwi");
结果:Banana,Orange,Lemon,Kiwi,Apple,Mango

//移除一个元素
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2,1,"Lemon","Kiwi");
结果:Banana,Orange,Lemon,Kiwi,Mango

//移除两个元素
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2,2);
结果:Banana,Orange

toString() 把数组转换成字符串,当然其他类型也可以转换,如var a=12;a.toString()
var fruits = ["Banana", "Orange", "Apple", "Mango"];
console.log(fruits.toString())

unshift() //向数组头部添加一个或多个元素并返回长度
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.unshift("Lemon","Pineapple");
返回值:6

函数

语法结构

//第一种声明-关键字
function name() {
	...
}

//function 是声明函数关键字
//()里写参数——形参
// {}里写代码块

//第二种声明-函数表达式
var a = function(){
    .....
}
a(); //调用函数

注意:如果实参多于形参,没什么事,实参不会被处理,相当于电灯泡;如果实参小于形参就会出问题,至于什么样的问题就要看函数里的代码块了,比如代码块是求和就会返回NaN

返回值:通过关键字return 来返回,return +变量;return +四则运算(目前知道就这些)

返回值附加

  1. 只返回一个值,并中止程序;要想返回多个值可以用其他数据结构,比如数组
function examp(a,b,c) {
    return [a,b,c];
}
console.log(st(1,2,3));
输出:[1,2,3]
  1. 函数如果没return 就会返回undefined

附加伪数组:具有数组的属性,但有些数组的方法不可用,比如push(),pop();其实大白话就是不是我们自己定义的数组,虚伪的存在着,用的时候才会出来

arguments关键字

这是函数的一个内置对象,数据类型是数组,作用是接受函数里所传递的任意数量参数

function can() {
	return arguments;
}
console.log(arguments)
输出:[]

如果要取形参里的特定一个参数,可以用下标来取;

可以被遍历(因为这是一个arguments伪数组)

作用域(es5 两种)

  1. 全局作用域

    整个script 标签里或整个js文件里

  2. 局部作用域

    在函数内部的函数名

变量作用域

  1. 全局变量作用域

    //特殊全局变量作用域
    function d() {
    		s=1;
    }
    d(); //要想让s变为全局作用域,就必须先执行这个函数
    console.log(s);
    

    销毁:当浏览器窗口页面关闭时才会销毁该变量,比较占内存

  2. 局部变量作用域

    销毁:当某个程序执行完后就销毁了,这样比较节约内存

块级作用域

注意:es5没有块级作用域,es6有

定义:花括号包含的就是块级作用域,比如,if () {} ;for () {} …

块级作用域里面的,外面不能去调用

例子-没有块级作用域

if (2<4){
			var s=1;
		}
		console.log(s);
输出:1 //可以发现,块里边的s变量在块外可被调用

作用域链

例子

var s=1; //外部作用域
function a(){
	var s=2; //局部作用域
	function b(){
		//局部作用域
		console.log(s);
	}
	return b();
}

console.log(a())
输出:2

定义:观察上面程序,虽然有两个变量s,对于最后一个函数来说都可以调用,但他只会调用最近的那一个,即s=2;

还可以发现,这三个作用域是套娃的,外部作用域套局部作用域,局部作用域再套下面的局部作用域,当最下边的局部作用域调用外部的作用域时只会往上一层一层的调用,不会直接调用顶层作用域,这就叫作链式查找

js预解析

  1. js引擎运行js代码分为两步:先预解析再执行

    (1) js引擎预解析会把var 和function预解析(提升)到当前作用域的最前面

    (2) 代码会从上往下执行

  2. 预解析分为变量预解析(变量提升)和函数预解析(函数提升)

    (1) 变量提升:只会提升到当前作用域的最前面不会赋值

    (2) 函数提升:只会提升到当前作用域的最前面不会调用

对象

小说:一提到对象,就会想起类,可学完javascript对象后,惊讶的发现没有类哎!查阅了一下,javascript确实没有类,具体原因可以看看javascript的历史。

什么时候需要对象?

当保存一个事物的完整信息时可以用对象,比如人的姓名、年龄、技能,对于一个变量来说是保存不了的

创建对象的三种方法

  1. new Object()创建对象
var b = new Object();
b.name = 'jack';
b.age = 18;
b.skill = function(){
	console.log('我会跳舞');
};

console.log(b.name)
console.log(b.['name'])
console.log(b.skill())
  1. 构造函数创建对象(用于构造相同的属性或方法的对象,有些像类,因此要new实例化)
function Car(name,price){
	this.name = name;
	this.price = price;
	this.skill = function(tex){
		console.log(tex);
	}
}

var c = new Car('tom',12);
console.log(c.name);
console.log(c.skill('haha'));
  1. 字面量{}创建对象
var a = {
    name:'tom',
    age:18,
    skill:function(){
        console.log('我会唱歌');
    }
}

console.log(a.name)
console.log(a.['name'])
console.log(a.skill())

遍历对象

var obj = {
    name:'tom',
    age:18,
    skill:function(){
        console.log('我会唱歌');
    }
}

for (var k in obj){
	console.log(k); //遍历名
	console.log(obj[k]); //遍历值
}

this关键字

相当于python的self,用于指定构造函数里的变量属于哪个实例

未完,待续…