JavaScript学习笔记

一、JS

JS的第一行代码

alert:发出警告

alert("这是我的第一行JS代码");

document:向body标签中添加内容

document.write("看我出不出来");

console.log():向控制台输出一个内容

console.log("你看我在哪里出来?");

JS代码的编写位置

可以将JS代码编写到标签的属性onclick中,只有当鼠标点击时,js代码才会执行。

<button onclick="alert('讨厌你点我干嘛?');">你点我一下</button>

也可以写在a标签的href属性中:

<a href="javascript:alert('让你点你就点???');">那你点我这里</a>

注:虽然可以写在标签的属性中,但是他们属于结构与行为耦合,不方便维护,不推荐使用!

也可以编写到script标签里或者在外部创建一个JavaScript文件,通过script标签在html中引入即可:

<script src="./script.js"></script>

script标签一旦引入外部文件就不能在其内部编写代码了,即是编写了浏览器也会忽略不会执行,如果需要可以在创建一个script标签用于编写内部js代码。

二、JS基本语法

注释:/*表示多行注释,//表示单行注释

JS中的一些基本编写语法特点
1、JS中严格区分大小写!!
2、JS每一条语句以;结尾,如果不写分号,浏览器会自动添加,但是会消耗一些系统资源,而且有些时候浏览器可能会加错分号,所以开发时必须写分号。
3、JS中会忽略多个空格和换行,所以可以利用空格和换行对代码进行格式化。

字面量和变量

字面量都是可以直接使用,但是一般都不会直接使用字面量。
变量:变量可以用来保存字面量,而且变量是可以任意改变的。变量更加方便我们使用,所以在开发中都是通过变量去保存字面量的。
声明变量:在js中使用关键字var来声明一个变量。

var a;
a=123;
var b=789;

标识符

命名一个标识符的规则:
1、标识符中可以含有字母、数字、_、$
2、标识符不能以数字开头
3、标识符不能是ES中的关键字或保留字。
4、标识符一般用驼峰法命名(首字母小写,每个单词的开头字母大写,其余小写)

JS底层保存标识符实际上是采用的Unicode编码,所以理论上所有的utf-8中含有的内容都可以作为标识符,但不建议使用。

数据类型

JS中的数据类型:string、Number、Boolean、Null、Undefined、Object(对象)

字符串

声明一个字符串:使用双引号或单引号都可以,但是不要混着用!

var str="hello";

在字符串中可以使用\作为转义字符。
\t:表示制表符。
\:表示\

Number数值

在JS中所有的数值都是Number类型,包括整数和浮点数。
可以使用typeof来检查一个变量的类型

var a="123";
console.log(typeof a);

JS中可以使用Number.MAX_VALUE表示数字的最大值,如果使用Number表示的数字超过了最大值,则会返回一个Infinity表示正无穷。
Infinity:实际上Infinity就是个字面量,如果想声明一个数字为正无穷,也是可以的。var a=Infinity;如果使用typeof检查a,那么返回的也是Number。
NaN:是一个特殊的数字,表示Not A Number。日过用typeof检查NaN,则返回的也时Number。
Number.MIN_VALUE:表示最小正值

在JS中整数的运算基本可以保证正确。但是如果使用JS进行浮点数的运算,可能得到一个不精确的结果。所以千万不要使用JS进行精确度要求比较高的运算。

Boolean布尔值

布尔值只有两个,true和false。
true表示逻辑上的真
false表示逻辑上的假
使用typeof检查时,返回boolean。

var bool=true;

NULL和Undefined

Null:NULL类型的值只有一个就是null。专门用来表示一个为空的对象。
使用typeof来检查一个NULL时,返回的是object

var a=null;

Undefined:Undefined类型的值只有一个就是undefined。当声明一个变量,但是并不给变量赋值时它的值就是Undefined。
使用typeof来检查时,返回的是undefined。

强制类型转换

将一个数据类型强制转换成其他的数据类型。
类型转换主要指将其他的数据类型转换为 String、Number、Boolean

转换为String的方法:

1、调用被转换数据类型的toString()方法。
注:该方法不会影响到原变量,他会将转换的结果返回a=a.toString();
局限性:null和undefined这两个值没用toString()方法,使用时会报错。

2、调用String()函数。使用String()函数做强制类型转换时,对于Number和Boolean实际上就是调用toString()方法;而对于null和undefined就不会调用调用toString()方法,会将null直接转换成字符串"null"

转换为Number的方法:

1、使用Number()函数将其它数据类型转换成Number类型。
若原始为字符串,如果是纯数字的字符串,则直接转换成数字;如果有非数字的字符串,则转换成NaN;如果字符串是个空串或全为空格的字符串,则转换成0;如果为布尔类型,则true转换成1,false转换成0;Null转换成0;undefined转换成NaN。

2、parseInt():可以将一个字符串中有效的整数内容取出来然后转换成Number
例如:a=“123.456”,调用parseInt()函数最终只能得到123.
parseFloat():作用和parseInt()类似,不同的是取出的是有效的小数。
例如:a=“123.456.789px”,调用parseFloat()得到的数是123.456
注:这两种函数专门用来针对于字符串转Number。对于非字符串使用这两种函数,它会将其先转换成String再操作。

3、可以对一个其它数据类型的前面使用+(正号),来将其转换成Number

补充:其他进制:
在JS中,十六进制用0x作为开头表示,八进制用0作为开头。
注:在进行强制类型转换时,例如"070"这种字符串转换成Number类型,有的浏览器会当成8进制进行解析,有的浏览器会当成十进制,为了统一,可以在使用parseInt()函数时,在后面传上第二个参数:用来指定进制类型。

var a="070";
a=parseInt(a,10);

转换为Boolean的方法:

1、使用Boolean()函数将其它数据类型转换成Boolean类型。
对于原始数据类型为数字的情况,除了0和null转换成false,其余都转换成true
对于原始数据类型为字符串的情况,除了空串其余都转换成true
对于原始数据类型为Null和Undefined,都是转换成false
对于原始数据类型为object,都是转换成true

2、隐式类型转换:使用!取反操作,可以将任意数据类型做两次非运算
,转换成布尔值。

运算符

运算符也叫作操作符。通过运算符可以对一个或多个值进行运算,并获取运算结果。
typeof就是一个运算符,作用是获取一个值的数据类型,它的返回值是一个字符串类型

var a=123;
var result=typeof a;
console.log(typeof result);

结果为String。

算术运算符

+、-、*、/、%等
当对非Number类型的值进行运算时,会将这些值转换为Number然后进行运算。任何值和NaN运算都得NaN。
+:
如果对两个字符串进行+运算就是将两个字符串相拼接!任何值和字符串进行+运算都会先转换成字符串再进行拼接!也可以利用这一种特点将任意数据类型转换成string类型,只需要将任意数据类型加上一个空串即可!

任何值做-、*、/运算时都会自动转换成Number,可以利用这一特点做隐式的强制类型转换,-0、*1、/1将其转换成Number。

%:取模运算(去余数)

一元运算符

+(正号)、-(负号):当对非Number类型的值进行运算时,会将这些值转换为Number然后进行运算。可以对一个其它数据类型使用+,来将其转换成Number,它的原理和Number()函数一样
e.g.

var result=1++"2"+3;
console.log("result="+result);

结果为result=6

逻辑运算符

:非运算符。取反操作。
&&:与运算符。
||:或运算符。
对于非布尔值的数据类型,会先将其转换成布尔值,再进行逻辑运算。返回的值:
在与运算中:如果第一个值为true,则返回第二个值;如果第一个值为false,则直接返回第一个值。
在或运算中:如果第一个值为true,则直接返回第一个值;如果第一个值为false,则直接返回第二个值。

关系运算符

> :大于号关系成立返回true,否则返回false
**>=**大于等于
<: 小于号关系成立返回true,否则返回false
<=:小于等于
对于非数字的类型,会先将其转换成数值在进行比较。
任何值和NaN做任何比较都是false。
如果关系运算符两侧都是字符串,则不会将其转换成数值,而是会比较Unicode字符编码,在比较字符编码时是一位一位进行比较的,如果两位一样,则比较下一位,所以可以借用它来对英文进行排序。

补充:有关Unicode的知识:
在字符串中使用转义字符输入Unicode编码。语法:\u四位编码
在网页标签中使用Unicode编码必须先转换成十进制。语法:&#编码;<h1>&#2620;</h1>

相等运算符

相等运算符“==”用来比较两个值是否相等。相等返回true,否则返回false。
当用相等运算符来比较两个值时,如果值的类型不同,则会自动进行类型转换,将其转换成相同的类型,然后再比较。
注:1、undefined是衍生于null,所以这两个值做相等判断时,返回的是true
2、NaN和任何值做相等判断都为false,包括他本身。
可以通过isNaN()函数来检查一个值是否是NaN。

不相等运算符!=:用来比较两个值是否不相等。当用不相等运算符来比较两个值时,如果值的类型不同,则会自动进行类型转换,将其转换成相同的类型,然后再比较。

全等===:判断两个值是否全等,与相等运算符类似,不同的是不会自动进行类型转换。

不全等!==:判断两个值是否不全等,与不相等运算符类似,不同的是不会自动进行类型转换。

条件运算符(三元运算符)

语法:条件表达式?语句1:语句2;
首先对条件表达式进行求值,若为true则执行语句1,若为false则执行语句2.
如果条件表达式的求值结果是一个非布尔值,则会将其转换为布尔值,然后再运算

补充:代码块:
在JS中可以使用{}来为语句进行分组,同一个{}中的语句我们称为是一组语句,要么都执行,要么都不执行。一个{}中的语句我们称为一个代码块,在代码块的后边就不用加;了
JS中的代码块只有分组的作用,代码块中的内容在外部是完全可见的。

流程控制语句

条件判断语句

if语句:if(条件表达式)语句

if(true)
     alert("值为真");

if-else语句:if(条件表达式){语句一;} else {语句二;}

补充:
prompt():可以弹出一个提示框,该提示框中会带有一个文本框,用户可以在文本框只能怪输入一段内容,该函数需要一个字符串作为参数,该字符串将会作为提示框的提示文字

var score=prompt("请输入小明的成绩:");

条件分支语句

switch:条件分支语句。
switch(条件表达式){
case 表达式一:
语句一
break;
case 表达式二:
语句二
break;
case 表达式三:
语句三
break;
default:
语句
break;
}

循环语句

while:先判断再执行
while(条件表达式){
语句;
}

do…while:先执行循环体,再进行判断
do{
}while(条件表达式)

for循环:
for(初始表达式;条件表达式;更新表达式){
}

三、对象

不是以上五种基本数据类型的都为对象。基本数据类型都是单一的值,值和值之间没有任何联系。如果使用基本数据类型,我们所创建的变量都是独立的不能成为一个整体。
对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性。
对象的分类:
1、内建对象:由ES标准中定义的对象,在任何的ES的实现中都可以使用
2、宿主对象:由JS的运行环境提供的对象,目前来讲主要是指由浏览器提供的对象,比如DOM、BOM
3、自定义对象:有开发人员自己创建的对象。

对象的基本操作

1、创建对象
使用new关键字调用的函数,是构造函数constructor,构造函数是专门用来创建对象的函数。
在对象中保存的值称为属性,向对象中添加属性。语法:对象.属性名=属性值。
读取对象中的属性:语法:对象.属性名
删除对象的属性:语法:delete 对象.属性名;

2、属性名和属性值
属性名:对象的属性名不强制要求遵守标识符的规范,但使用时尽量按照标识符的规范。如果要使用特殊的属性名,不能采用.的方式,需要使用另一种方式:对象[“属性名”]=属性值,读取也要采取这种方式。
使用[]这种形式去操作属性,更加的灵活,在[]中可以直接传递一个变量,这种变量值是多少就会读取那个属性。

属性值:JS对象的属性值可以是任意的数据类型。甚至也可以是一个对象。

in运算符:通过该运算符可以检查一个对象中是否含有某个属性。语法:“属性名” in 对象

3、基本数据类型和引用数据类型
JS的变量都是保存到栈内存的,基本数据类型的值直接在栈内存中存储。值与值之间是相互独立存在的,修改一个变量不会影响其他的变量。
对象是保存到堆内存中的,每创建一个新的对象,就会在堆内存中开辟出一个新的空间。而变量保存的是对象的内存地址(对象的引用),如果两个变量保存的是同一对象的引用,当一个通过变量修改属性值时,另一个也会受到影响。
当比较两个基本数据类型时,就是比较他们的值;而比较两个引用数据类型时,他是比较对象的内存地址,如果两个对象是一模一样但内存地址不同,会返回false。

对象字面量

可以使用对象字面量{}来创建对象。可以在创建对象时,直接指定对象中的属性。语法:{属性名:属性值,属性名:属性值;},其中对象的属性名可加可不加双引号,但是如果要命名一些特殊的属性名最好加上双引号。属性名和属性值是一组一组的名值对结构,名和值之间使用:隔开多个名值对之间用,隔开,最后一个名值对就不用再加,了

var obj={
     name:"周深",
     age:29,
     gender:"男"
}

四、函数

函数也是一个对象。函数中可以封装一些功能(代码),在需要时可以执行这些功能。函数中可以保存一些代码在需要是被调用。

创建函数对象

1、使用new关键字(很少用,几乎不用)

var fun=new Function();

调用函数对象:语法:函数对象()

fun();

2、使用函数声明来创建一个函数:语法:
function 函数名[形参1,形参2,…]{
语句;
}

3、使用函数表达式创建一个函数
var 函数名=function([形参1,形参2,…]){ 语句; }

立即执行函数

立即执行函数:函数顶一万,立即被调用,这种函数被叫做立即执行函数。立即执行函数往往只会执行一次。

(function(a,b){
            console.log("a="+a);
            console.log("b="+b);
        })(123,456);

方法

对象的属性值可以是任何数据类型,函数也可以称为对象的属性,如果一个函数作为一个对象的属性保存,那么我们称这个函数是对象的方法,调用这个函数就说调用对象的方法。

枚举:枚举对象中的属性,使用for… in语句
语法:for(var n in 对象名){}

var obj={
    name:"周深",
    age: 29,
    address: "贵阳"
};
for(var n in obj){
    console.log("属性名:"+n);
    console.log("属性值:"+obj[n]); //调用属性值
}

作用域

作用域指一个变量的作用的范围。在JS中有两种作用域:全局作用域和函数作用域。

全局作用域

全局作用域:直接编写在script标签中的JS代码,都在全局作用域中。全局作用域在页面打开是创建,页面关闭时销毁。
在全局作用域中有一个全局对象window,他代表的是一个浏览器的窗口,它由浏览器创建我们可以直接使用。在全局作用中,创建的变量都会作为window对象的属性保存,创建的函数都会作为window对象的方法保存。

函数作用域

函数作用域:调用函数时创建函数作用域,函数执行完毕函数作用域销毁。
没屌用用一次函数就会创建一个新的函数作用域,它们之间是相互独立。
在函数作用域中可以可以访问到全局作用域变量,在全局作用域中无法访问到函数作用域的变量。
如果在函数中想访问全局中的变量,可以使用window。

如果在函数中没有使用var声明变量,则该变量为全局变量,在函数外也可以访问该变量!!!!
定义形参就相当于在函数作用域中声明了变量
如果定义了形参,在函数中声明变量没有使用var那么这个变量就不是全局变量。

this

解析器在调用函数时每次都会向函数内部传递一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象我们称为函数执行的上下文对象,根据函数的调用方式不同,this会指向不同的对象。
1、以函数的形式调用时,this永远都是window
2、以方法的形式调用时,this就是调用方法的那个对象。
3、使用构造函数的形式调用时,this就是新创建的那个对象
4、使用call()和apply()方法调用时,this就是传递的第一个参数

工厂方法创建对象

function creatPerson(name,age,address){
    var obj=new Object();
    obj.name=name;
    obj.age=age;
    obj.address=address;
}

var obj1=creatPerson("周深",29,"贵阳");

构造函数

工厂方法创建对象的缺点:
使用工厂方法创建的对象,使用的构造函数都是Object,所以创建的对象都是Object的类型,导致无法区分出多种不同类型的对象。
创建一个构造函数,专门用来创建Person对象的,构造函数就是一个普通的函数,不同的是构造函数习惯上首字母大写。
构造函数和普通函数的区别就是调用的方式不同,普通函数调用方式就是直接调用,而构造函数调用方式是使用new关键字。
构造函数的执行流程
1、立即创建一个新的对象
2、将新建的对象设置为函数中的this,在构造函数中可以使用this来引用新建的对象。
3、逐行执行函数中的代码
4、将新建的对象作为返回值返回

function Person(name,age,address){
    this.name=name;
    this.age=age;
    this.address=address;
}

var obj1=new Person("周深",29,"贵阳");   //其中obj1就是一个实例

可以使用instanceof检查一个对象是否是一个类的实例。

console.log(obj1 instanceof Person);

原型对象

我么所创建的每一个函数,解析器都会向函数中添加一个属性prototype,这个属性对应着一个对象,这个对象就是所谓的原型对象。

如果作为普通函数调用prototype没有任何作用,当函数以构造函数调用,他所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,我们可以通过_proto_来访问该属性。

原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。

当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到直接使用。

以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,这样不用分别为每一对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了。

function MyClass(){
    
}

MyClass.prototype.name="周深";//在MyClass类的原型对象中添加属性。

var obj1=new MyClass();
console.log(obj1.name);//obj1中没有name,但可以在原型对象中找到。

可以使用hasOwnProperty()来检查对象自身中是否含有该属性,使用该方法只有当对象自身中含有该属性时才会返回true

console.log(obj1.hasOwnProperty("name"));

当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到直接使用。如果在原型对象中没有找到,就去原型对象的原型去找,直到找到Object对象的原型。Object对象的原型没有原型,如果在Object中依然没有找到,则返回undefined。

toString()

当我们直接在页面中打印一个对象时,实际上是输出的对象的toString()方法的返回值,如果我们不希望在输出对象时不输出[Object Object],可以为对象添加一个toString()方法

function MyClass(name,age,address){
    this.name=name;
    this.age=age;
    this.adress=address;
}

MyClass.prototype.toString=function(){
    return MyClass[name="+this.name+",age="+this.age+",address="+this.address+"];
}

var obj1=new MyClass("周深",29,"贵阳");
console.log(obj1);

垃圾回收(GC)

当一个对象没有任何的变量或属性对他进行引用,此时我们将无法操作该对象,这种对象就是一个垃圾,当这种对象过多会占用大量的内存空间,导致程序运行变慢,所以这种垃圾必须清理。
在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收操作。
我们需要做的就是将不再需要使用的对象设置为NULL即可

五、数组

数组的基本操作

数组(Array):也是一个对象。
1、创建数组对象:

var arr new Array();

向数组中添加元素:

arr[0]=10;

读取数组中的元素:

console.log(arr[0]);

获取连续数组的长度:

console.log(arr.length);

修改length的长度:如果修改后的长度大于原长度,则多出部分会空出来,如果修改后的长度小于原长度,则多出的元素会被删除。

向数组的最后一个位置添加元素:

arr[arr.length]=20;

2、使用字面量创建一个数组,可以在创建时就指定数组中的元素。

var arr=[1,2,3,4];

3、使用构造函数创建数组时,也可以同时添加元素,将要添加的元素作为构造函数的参数传递元素之间用,隔开

var arr=new Array(1,2,3);

数组的方法

push():向数组的末尾添加一个或多个元素,并返回数组的长度

var result=arr.push("周深",29,"贵阳");
console.log(arr);
console.log("result="+result);

pop():可以删除数组最后一个元素,并将删除的元素作为返回值返回

unshift():向数组的开头添加一个或多个元素,并返回数组的长度。其他元素的索引会依次调整。

shift():可以删除数组第一个元素,并将删除的元素作为返回值返回

forEach():用来遍历数组(只支持IE8以上的浏览器)forEach()方法需要一个函数作为参数。像这种函数,由我们自己创建,但是不由我们调用的,我们称之为回调函数。数组中有几个元素函数就会执行几次,每次执行时,浏览器会将遍历到的元素以实参的形式传递进来,我们可以用来定义形参,来读取这些内容。

var arr=[1,2,3,4];

arr.forEach(function(value,index,obj){
    console.log();
})

浏览器会在回调函数中传递三个参数:
第一个参数:就是当前正在便利的元素
第二个参数:就是当前元素的索引
第三个参数:就是正在遍历的数组

slice():从数组中提取指定元素

arr.slice(start,end);

该方法不会影响到原数组,而是将截取到的元素封装到一个新的数组中并返回。包含开始索引,不包含结束索引索引也可以是负值,如果是负值,则表示从后往前计算。

splice():用于删除数组中的指定元素,并添加新的元素
使用该方法会影响到原数组,会将指定元素从原数组中删除,并将删除的元素作为返回值返回.第二个参数表示删除元素的个数,第三个元素及以后可以传递一些新的元素,这些元素将会自动插入到开始位置索引的前边

arr.splice(start,n,"a");

concat():连接两个或多个数组,并将新的数组返回(该方法不会影响到原数组)

arr.concat(arr2);

join():可以将数组转换成一个字符串,并将新的字符串返回(该方法不会影响到原数组)可以在join()中指定一个字符串作为参数,这个字符串将会作为数组中元素之间的连接符,如果不指定连接符,则默认为,作为连接符

arr.join("-");

reverse():用来反转数组(该方法会直接影响到原数组)

sort():用来对数组中的元素进行排序(该方法会直接影响到原数组)会默认按照Unicode编码进行排序。如果为纯数字使用sort方法进行排序可能会发生错误,所以需要自己制定排序。规则:
在sort()中添加一个回调函数,来制定排序规则。浏览器会根据回调函数的返回值来决定元素的排序:
如果返回一个大于0的值,则元素会交换位置
如果返回一个小于0的值,则元素不会交换位置
如果返回0,则默认元素相等,也不交换位置

如果需要升序排列,则返回a-b;降序返回b-a:

var arr=[11,4,6,2,8,5];

arr.sort(function(a,b){
    return a-b;
})
console.log(arr);

函数对象的方法

call()和apply():需要通过函数对象来调用,当对函数调用call()和apply()都会执行调用函数。在调用call()和apply()可以将第一个对象指定为第一个参数,此时这个对象将会成为函数执行的this;
call()方法可以将实参在对象之后依次传递
apply()方法需要将实参封装到一个数组中统一传递

arguments

arguments是一个类数组对象,他也可以通过索引来操作数据,也可以获取长度,在调用函数时,我们所传递的实参都会在arguments中保存。arguments.length可以用来获取实参的长度。也可以使用arguments[]来使用实参。其中还有个属性叫callee,这个属性对应一个函数对象,就是当前正在使用的函数的对象。

Date对象

1、创建Date对象
在JS中使用Date对象来表示一个时间。
如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间:

var d=new Date();

如果想要创建一个指定的时间对象,需要在构造函数中传递一个表示时间的字符串作为参数。

var d2=new Date("05/11/1999 00:00:00");

2、Date方法:
getDate():获取当前日期对象是几日。

getDay():获取当前日期是周几。会返回一个0-6的值,0表示周日

getMonth():获取当前日期是月份,0表示1月,1表示2月

getFullYear():获取当前日期对象的年份

getTime():获取当前日期对象的时间戳。时间戳是从格林威治标准时间的1970年1月1日,0时0分0秒到当前日期所花费的毫秒数(1秒=1000毫秒)
计算机底层在保存时间时使用的都是时间戳

Date.now():获取当前的时间戳,利用时间戳来测试代码的执行的性能。

Math

Math和其他的对象不同,他不是一个构造函数,他属于一个工具类不用创建对象,他里边封装了数学运算相关的属性和方法。
比如:Math.PI表示圆周率
Math的方法:
Math.ceil():可以对一个数进行向上取整

Math.floor():可以对一个数进行向下取整

Math.round():可以对一个数进行四舍五入

**Math.random() **:可以用来生成一个0-1之间的随机数;如果想生成0-10之间的随机数可以直接乘10:

Math.random()*10

如果想生成0-10之间的整数可以:

Math.round(Math.random()*10);

如果想生成x-y之间的随机数:

Math.round(Math.random()*(y-x)+x);

max():最大值
min():最小值
pow(x,y):返回x的y次幂
sqrt():用于对一个数进行开方计算

包装类

在JS中提供了三种包装类:
String():可以将基本数据类型的字符串转换为String对象
Number():可以将基本数据类型的数字转换成Number对象
Boolean():可以将基本数据类型的布尔值转换成Boolean对象
注:我们在实际应用中不会使用基本数据类型的对象,如果使用基本数据类型的对象在做一些比较时可能会带来一些错误。

字符串的方法

在计算机底层字符串是以字符数组的形式储存的。
比如一个字符串“Hello”,在计算机底层:[“H”,“e”,“l”,“l”,“o”]

字符串的方法
1、charAt():可以返回字符串中指定位置的字符,根据索引获取指定的字符。str.charAt(6);
2、charCodeAt():获取指定位置字符的字符编码(Unicode编码)str.charCodeAt(6)
3、formCharCode():根据字符编码去获取字符。

String.formCharCode(200);

4、concat():可以连接两个或多个字符串,作用和+一样(不会对原字符串产生影响)

5、indexof():可以检索一个字符串是否含有指定内容,并返回该内容第一次出现的索引,如果没有找到则返回-1.第二个参数表示从第几个位置开始查找。str.indexof("a",3);

6、lastIndexOf():从后往前找,和上面indexof类似。

7、slice():可以从字符串中截取制定的内容。不影响原字符串,将截取内容返回。参数:包括开始位置不包括结束位置。

8、substring():可以用来截取一个字符串。第一个参数表示开始位置截取,第二个参数表示截取的结束位置,包括开始不包括结束位置。与slice不同的是,该方法不可以传递负数,如果传递了负数则默认为0,如果第二个参数值小于第一个参数,则会自动调整位置。

9、substr():用来截取字符串。第一个参数表示截取的开始位置,第二个参数表示截取的字符串的长度。

10、split():可以将一个字符串拆分为一个数组。参数:需要一个字符串作为参数,将会根据该字符串进行拆分。如果传递的参数为空串,则会将原字符串中的每一个字符拆分为数组的元素。

11、toUpperCase():将字符串转换为大写

12、toLowerCase():将字符串转换为小写

六、正则表达式

创建正则表达式

1、创建正则表达式对象:
语法:
var 变量=new RegExp(“正则表达式”,“匹配模式”);
var var=new RegExp(“a”);这个正则表达式可以来检查一个字符串中是否含有a。
在构造函数中可以传递第二个参数用来表示匹配模式:
其中i表示忽略大小写,g表示全局匹配模式

正则表达式的方法:
test():使用这个方法可以用来检查一个字符串是否符合正则表达式的规则,如果符合返回true

2、使用字面量来创建正则表达式:
语法:var 变量=/正则表达式/匹配模式

正则语法

1、使用|表示或的意思:

reg=/a|b|c/;

2、使用[]里的内容也是或的意思:[ab]表示a或b;[A-Z]表示任意大写字母

reg=/[a-z]/;

3、检查一个字符串中是否含有abc或adc或aec

reg=/a[bde]c/;

4、[^ ]表示除了后边的内容:

reg=/[^0-9]/; //除了数字

字符串和正则相关

split():可以将正则表达式作为参数进行字符串的拆分:

var str="1a2b3d4e";
var result=str.split("/[A-z]/");

search():可以将正则表达式作为参数进行指定字符串的搜索

match():可以将正则表达式作为参数

电子邮件的正则表达式

规则:
任意字母下划线 .任意字母下划线(可出现也可不出现) @ 任意字母数字 .任意字母(2-5位) .任意字母(2-5位)(可有可无)

\w{3,}  (\.\w+)*  @  [A-z0-9]+   (\.[A-z]{2,5}){1,2}
var emailReg=/^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/;

七、DOM

DOM的简介

DOM:Document Object Model 文档对象模型(用来操作网页的)
文档:一个网页就是一个文档
对象:表示将网页的每一个部分都转换为一个对象。
模型:使用模型来表示对象之间的关系

在这里插入图片描述
节点:是构成网页的最基本的组成部分分为四类:
1、文档节点:整个html文档
2、元素节点:html文档中的html标签
3、属性节点:元素的属性
4、文本节点:html标签中的内容

节点的属性

在这里插入图片描述

文档节点:浏览器已经为我们提供文档节点对象,这个对象是window属性,可以在页面中直接使用,文档节点代表的使整个网页。
例如获取button对象:

<body>
    <button id="btn">我是一个按钮</button>
    <script>
        var btn=document.getElementById("btn");//获取button对象
        btn.innerHTML="I'm Button";//修改button中的文字
    </script>
</body>

获取元素的节点
1、getElementById():通过id属性获取一个元素节点的对象
2、getElementsByTagName():通过标签名获取一组元素节点对象
3、getElementsByName():通过name属性获取一组元素节点对象。

事件

就是文档或浏览器窗口中发生的一些特定的交互瞬间。用户和浏览器之间的交互行为。
1、我们可以在事件对应的属性中设置一些js代码,这样当事件被触发时,这些代码将会执行。但这种写法不方便维护,不推荐使用!

<button id="btn" ondblclick="alert('讨厌,你点我干嘛?');">我是一个按钮</button> <!--双击是出现alert警示-->

2、可以为按钮的对应事件绑定处理函数的形式来响应事件,这样当事件被触发时,其对应的函数将会被调用。

        //获取对象
        var btn=document.getElementById("btn");
        btn.onclick=function(){
            alert('讨厌,你点我干嘛?');
        }

像这种为单击事件绑定的函数称为单击响应函数。

文档的加载

浏览器加载页面的顺序是自上向下的顺序,读取一行运行一行。如果将script标签的内容写到上面去,在代码执行时,页面还没有加载。将js代码编写到页面的下面是为了可以在页面加载完毕后再执行js代码。

如果想把代码卸载head标签里但又不想先执行,可以使用onload事件。
onload事件会在整个页面加载完成之后才触发。
为window绑定一个onload事件,该事件对应的响应函数会在页面加载完成后执行,这样就可以确保我们的代码执行时所有的DOM对象已经加载完毕了。

DOM 查询

1、通过document对象调用来获取元素的节点:
getElementById():通过id属性获取一个元素节点的对象
getElementsByTagName():通过标签名获取一组元素节点对象
getElementsByName():通过name属性获取一组元素节点对象。

2、通过具体的元素节点调用,获取元素的子节点:
getElementsByTagName():返回当前节点指定标签名后代节点
childNodes:是属性,表示当前节点的所有子节点。会获取包括文本节点在内的所有节点,根据DOM标签间空白也会被当成文本节点
注意:在IE8及以下的浏览器中,不会将空白当成子节点

children:是属性,可以获取当前元素的所有子元素。

firstchild:是属性,表示当前节点的第一个子节点(包括空白文本节点!)

firstElementChild:获取当前元素的第一个子元素。(不支持IE8及以下浏览器,不推荐使用)

lastchild:是属性,表示当前节点的最后一个子节点

3、通过具体的元素节点调用,获取元素的父节点和兄弟节点
parentNode:是属性,获取当前节点的父节点

previousSibling:是属性,获取当前节点的前一个兄弟节点(包括空白文本节点!)

previousElementSibling:获取当前节点的前一个兄弟元素。(不支持IE8及以下浏览器,不推荐使用)

nextSibling:是属性,获取当前节点的后一个兄弟节点(包括空白文本节点!)

innerHTML:获取到元素内部的文本内容(包括标签)
innerText:获取到元素内部的文本内容,和上面类似,不同的是会自动去除掉html标签

4、DOM查询的其他方法:
document.body:是属性,在document中有一个属性body,他保存的就是body的引用。

document.documentElement:获取html根标签

document.all:代表页面中的所有元素(html、body、head等)

getElementsByClass():根据元素的class属性值获取一组元素节点对象,但是该方法不支持IE8及以下的浏览器

querySelector():需要一个选择器的字符串作为参数,可以根据一个CSS选择器来查询一个元素节点对象。(IE8既然好使)。使用该方法总会返回唯一的一个元素如果满足条件的元素有多个,那么它只会返回第一个

var li=document.querySelector(".box1 li");

querySelectorAll():与上面类似,不同的是他会将符合条件的元素封装到一个数组中返回。即使符合条件的元素只有一个,也会封装到数组中返回。

DOM的增删改

document.createElement():可以用于创建一个元素节点对象。它需要一个标签名作为参数,将根据该标签名创建元素节点对象,并将创建好的对象作为返回值返回。

document.createTextNode():可以用来创建一个文本节点对象,它需要一个文本内容作为参数,将根据该文本内容创建文本节点,并将创建好的新的节点返回。

appendChild():向父节点中添加一个新的子节点。
用法:父节点.appendChild(子节点);

insertBefore():在指定的子节点前面插入新的子节点
语法:父节点.insertBefore(新节点,旧节点)

replaceChild():可以使用指定的子节点替换已有的节点。
语法:父节点.replaceChild(新节点,旧节点)

removeChild():可以删除一个子节点
语法:父节点.removeChild(子节点);或
子节点.parentNode.removeChild(子节点)

使用innerHTML也可以实现DOM增删改的相关操作:(例如添加一个li)

city.innerHTML+="<li>广州</li>";

一般是两种方式结合使用:(推荐使用这种方式!)

var li=document.createElement("li");
li.innerHTML="广州";
city.appendChild(li);

confirm():用于弹出一个带有确认和取消按钮的提示框,需要一个字符串作为参数,该字符串将会作为提示文字显示出来,用户点确认则返回true,点取消则返回false

使用DOM操作CSS

语法:元素.style.样式名=样式值

btn01.onclick=function(){
                box1.style.width="500px";
                box1.style.height="500px";
                box1.style.backgroundColor="red";
            };

注:通过style属性设置的样式都是内联样式,而内联样式具有较高的优先级,所以通过JS修改的样式往往会立即显示
但是如果在样式中写了!important,则此时样式会具有更高的优先级,即使通过js也无法改变。

注:通过style属性读取和设置的都是内联样式,无法读取样式表中的样式!!!

DOM读取样式表

1、获取当前元素正在显示的样式(只有IE支持)
语法:元素.currentStyle.样式名

2、getComputedStyle()方法:获取当前元素正在显示的样式。
两个参数:第一个参数:要获取的元素
第二个参数:可以传递一个伪元素,一般都传null
返回一个对象,对象中封装了当前元素对应的样式

 btn01.onclick=function(){
                var obj=getComputedStyle(box1,null);
                alert(obj.width);
            };

注:如果获取的样式没有设置,不会得到auto默认值,而是得到真实的值,比如没有设置width,并不会得到auto,而是一个真实的长度;背景颜色获取到的是rgba(不支持IE8及以下)

特别注意:通过currentStyle和getComputedStyle()方法获取到的样式都是只读的不可以进行修改,如果想要修改样式,只能通过style的方式!!!

3、定义一个函数getStyle()用来获取当前元素显示的样式

function getStyle(obj,name){
            if(window.getComputedStyle){
                return(getComputedStyle(obj,null)[name]);
            }
            else{
                return obj.currentStyle[name];
            }
        };
window.onload=function(){
            //要求:单击按钮修改盒子的大小
           //获取盒子对象
            var box1=document.getElementById("box1");
           //获取按钮对象
            var btn01=document.getElementById("btn01");
           //为按钮绑定单击响应事件
            btn01.onclick=function(){
                alert(getStyle(box1,"width")); //一定要加双引号!
            };
        };

其他样式相关属性

clientWidth和clientHeight
这两个属性可以获取元素的可见宽度和高度。这两个属性返回的都是不带单位px的数字,可以直接进行计算。
这两个会获取元素宽度和高度包括内容区和内边距,这两个属性都是只读不可修改!

offsetWidth和offsetHeight
可以获取元素整个的宽度和高度,包括内容区和内边距和边框。

offsetParent:可以用来获取当前元素的定位父元素。即获取到离当前元素最近的开启定位的祖先元素。若所有的祖先元素都没有开启定位,则直接返回body

offsetLeft :当前元素相对于其定位父元素的水平偏移量

offsetTop:当前元素相对于其定位父元素的垂直偏移量

scrollWidth和scrollHeight
可以获取元素整个滚动区域的宽度和高度

scrollLeft:获取水平滚动条滚动的距离

scrollTop:获取垂直滚动条滚动的距离

注**:判断滚动条是否到底?**
当满足scrollHeight-scrollTopclientHeight时,说明垂直滚动条滚动到底了
当满足scrollWidth-scrollLeft
clientWidtht时,说明水平滚动条滚动到底了

事件对象

事件对象:当事件响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数。在事件对象中封装了当前事件相关的一切信息,比如:鼠标的坐标,键盘哪个按键被按下, 鼠标滚轮滚动的方向。
clientX:可以获取鼠标指针的水平坐标
clientY:可以获取鼠标指针的垂直坐标
注:在IE8中,响应函数被触发时,浏览器不会传递事件对象,在IE8及以下的浏览器中,是将事件对象作为window对象的属性保存的
pageX和pageY:相对于文档(当前页面)的水平和垂直坐标

事件的冒泡

所谓的冒泡指的就是事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发。
在开发中大部分时候的冒泡是有用的,如果不希望发生事件冒泡可以通过时间对象来取消

event.cancelBubble=true;

事件的委派

是指事件统一绑定给元素的共同祖先元素,这样当后代元素上的事件被触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。
事件的委派是利用了冒泡,通过委派可以减少事件绑定的次数
比如:按动按钮可以添加新的超链接,但是按动超链接就没有和已经存在的超链接有统一的事件绑定,需要重新为新增的超链接进行事件的绑定,这样操作十分麻烦,所以,可以直接为他们的祖先元素进行事件的绑定。

补充:event事件中的target表示触发事件的对象

事件的绑定

使用 “对象.事件=函数” 的形式绑定响应函数,它只能同时为一个元素的一个事件绑定一个响应函数,不能绑定多个,如果绑定了多个,后面的则会覆盖前面。

addEventListener():通过这个方法也可以为元素绑定响应函数
参数:
1、事件的字符串,不要on
2、回调函数,当事件触发时,函数被调用
3、是否在捕获阶段触发事件,需要一个布尔值,一般都传false
使用addEventListener()可以同时为一个元素的相同事件绑定多个响应函数,这样当事件被触发时,响应函数将会按照函数的绑定顺序执行。但这个方法不支持IE8及以下!!
addEventListener()中的this是绑定事件的对象

在IE8及以下:
attachEvent():来绑定事件
参数:
1、事件的字符串,要on
2、回调函数,当事件触发时,函数被调用
attachEvent()中的this是window

可以直接定义一个函数:bind函数

function bind(obj,eventstr,callback){
            if(obj.addEventListener){
                obj.addEventListener(eventstr,callback,false);
            }
            else{
                obj.attachEvent("on"+eventstr,function(){
                    //在匿名函数中调用回调函数
                    callback.call(obj);
                });
            }
        }

事件的传播

W3c将事件的传播分成三个阶段:
1、捕获阶段:在捕获阶段时,从最外层的祖先元素向目标元素进行事件的捕获,但是默认此时不会触发事件。
2、目标阶段:事件捕获到目标元素,捕获结束开始在目标元素上触发事件
3、冒泡阶段:事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件

如果希望在捕获阶段就触发事件,可以将addEventListener()方法中的第三个参数设置为true,,但是一般情况下不会再捕获阶段就触发事件,所以这个参数一般都是false
IE8及以下的浏览器中没有捕获阶段。

滚轮事件

onmousewheel鼠标滚轮滚动的事件,会在滚轮的滚动时触发,但是火狐不支持。
在火狐中需要使用DOMMouseScroll来绑定滚轮滚动事件,注意:该事件需要用addEventListener()函数来绑定

event.wheelDelta:可以获取鼠标滚轮滚动的方向(向上滚为正,向下则为负)
但是火狐不支持wheelDelta,在火狐中需要使用event.Detail来获取滚轮滚动的方向,向上滚为负,向下为正。

使用addEventListener()函数方法绑定响应函数,取消默认行为时不能使用return false;需要使用event来取消默认行为:event.preventDefault();;但是IE8又不支持event.preventDefault(),如果直接使用则会报错!
添加如下代码即可:

event.preventDefault && event.preventDefault();

键盘事件

onkeydown和onkeyup:按键被按下和松开;
键盘事件一般都会绑定给一些可以获取到焦点的对象或者document
onkeydown:如果按键一直不释放,则事件会连续触发。
当onkeydown连续触发时,第一次和第二次之间会间隔稍微长一点,其他的会非常快。这种设计是为了防止误操作的发生

onkeyup:是不会连续触发的!

KeyCode:可以通过这个来获取按键的编码,通过他可以判断哪个按键被按下。
数字0-9的KeyCode为48-57

除了KeyCode,事件对象中还提供了几个属性:
altKey:
ctrlKey:
shiftKey:

这三个用来判断alt,ctrl和shift是否被按下

八、BOM

BOM:浏览器对象模型。BOM可以使我们通过JS来操作浏览器,在BOM中为我们提供了一组对象,用来完成对浏览器的操作
BOM对象有:
window:代表的是整个浏览器窗口,同时window也是网页中的全局对象

Navigator:代表当前浏览器信息,通过该对象可以识别不同的浏览器

Location:代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面

History:代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录。由于隐私的原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页,而且该操作只在当次访问时有效

Screen:代表用户的屏幕的信息,通过该对象可以获取到用户的显示器的相关信息。

这些对象(除了window)在浏览器中都是作为window对象的属性保存的,可以通过window对象来使用,也可以直接使用,例如:window.navigatorlocation

Navigator

代表当前浏览器信息,通过该对象可以识别不同的浏览器。由于历史原因,Navigator对象中的大部分属性已经不能帮助识别浏览器了

userAgent
一般只会使用userAgent来判断浏览器信息,这个字符串中包含有用来描述浏览器信息的内容,不同的浏览器会有不同的userAgent

 var ua=navigator.userAgent;
        if(/firefox/i.test(ua)){
            alert("你是火狐浏览器");
        }
        else if(/chrome/i.test(ua)){
            alert("你是chrome浏览器");
        }
        else if(/msie/i.test(ua)){
            alert("你是IE浏览器~")
        }

注:在IE11中已经将微软和IE相关的标识都已经去除了,所以我们基本不能通过userAgent来识别一个浏览器是否是IE了

如果不能通过userAgent来判断,还可以通过一些浏览器中特有的对象,来判断浏览器的信息。比如:ActiveXObject(只有IE浏览器有)
故可以对以上代码进行改进:

if(/firefox/i.test(ua)){
            alert("你是火狐浏览器");
        }
        else if(/chrome/i.test(ua)){
            alert("你是chrome浏览器");
        }
        else if(/msie/i.test(ua)){
            alert("你是IE浏览器~")
        }
        else if("ActiveXObject" in window){
            alert("你是IE11浏览器!");
        }

History

可以操作浏览器向前或向后翻页。

属性:
length:可以获取到当次访问的链接数量

方法:
back():可以用来回退到上一个页面,作用和浏览器中的回退按钮一样

forward():可以跳转到下一个页面,作用和浏览器中的前进按钮一样

go():可以跳转到指定的页面,需要一个整数来作为参数:1表示向前跳转一个页面(相当于forward()方法);2表示向前跳转两个页面;-2表示向后跳转两个页面。

Location

代表当前浏览器的地址栏信息。
如果直接打印location,则可以获取到地址栏信息(当前页面的完整路径)
如果直接将location属性修改为一个完整的路径,或相对路径,则页面会自动跳转到该路径,并且会生成相应的历史记录。

方法:
assign():用来跳转到其他页面,作用和直接修改location一样

reload():用于重新加载页面,作用和浏览器中的刷新按钮一样。如果在该方法中传递一个true作为参数,则会强制清空缓存,刷新页面

replace():可以使用一个新的页面替换当前页面,调用完毕也会跳转页面。但是这个方法不会生成历史记录,不能使用回退按钮回退。

定时器

如果希望一段程序,可以每间隔一段时间执行一次,可以使用定时调用。

setInterval():定时调用,可以将一个函数每隔一段时间执行一次。
参数:
1、回调函数,该函数每隔一段时间调用一次
2、每次调用间隔的时间,单位是毫秒
返回值:返回一个Number类型的数据,这个数字用来作为定时器的唯一标识。

clearInterval():可以用来关闭一个定时器,该方法需要传递定时器的唯一标识作为参数,这样将关闭标识对应的定时器。
clearInterval()可以接收任意参数,如果参数是一个有效的定时器标识,则停止对应的定时器,如果参数不是一个有效的标识,则什么也不做。

练习:定时器数字从1-7,每一秒变一次

<script>
    var num=1;
    var timer=setInterval(function(){
        count.innerHTML=num++;
        if(num ==8){
            clearInterval(timer);
        }
    },1000);
</script>
<body>
    <h1 id="count"></h1>
</body>

延时调用

setTimeout():延时调用。延时调用一个函数不马上执行,而是隔一段时间后再执行,而且只会执行一次
延时调用和定时调用的区别,定时调用会执行多次,而延时调用只会执行一次。

clearTimeout():用来关闭一个延时调用。

九、类的操作

一行代码可以同时修改多个样式。
方法:修改元素的class属性。通过修改其class属性来间接的修改样式,只需一行代码就可以同时修改多个样式,浏览器只需要渲染页面一次,性能比较好。这种方式可以使表现和行为进一步分离

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .b1{
            width: 200px;
            height: 200px;
            background-color: black;
        }
        .b2{
            width: 300px;
            height: 300px;
            background-color: bisque;
        }
    </style>
    <script>
        window.onload=function(){
            var btn=document.getElementById("btn");
            var box=document.getElementById("box");
            btn.onclick=function(){
                box.className+=" b2"; //类的操作,一定要有空格!!!!
            };
        };
    </script>
</head>
<body>
    <button id="btn">点击我</button><br><br>
    <div class="b1" id="box"></div>
</body>

定义一个函数addClass用来向一个元素中添加指定的class属性值
参数:obj指定的对象,cn要添加的class值

function addClass(obj,cn){
            if(!hasClass(obj,"b2")){
                obj.className+=" "+cn;
            }
            
        }

定义一个函数hasClass用来判断该元素中是否含有类
有则返回true,没有就返回false

function hasClass(obj,cn){
            var reg=new RegExp("\\b"+cn+"\\b");
            return (reg.test(obj.className));
        }

定义一个函数removeClass用来删除元素中的类

function removeClass(obj,cn){
            var reg=new RegExp("\\b"+cn+"\\b");
            obj.className=obj.className.replace(reg,"");
        }

定义一个函数toggleClass用来切换属性。如果该元素中没有类则添加,如果有则删除

function toggleClass(obj,cn){
            if(hasClass(obj,cn)){
                removeClass(obj,cn);
            }
            else{
                addClass(obj,cn);
            }
        }

十、JSON

JSON:就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别,并且可以转换为任意语言中的对象,JSON在开发中主要是用来数据的交互。
JSON和JS对象的格式一样,只不过JSON字符串中的属性名必须要加双引号,其他的和JS语法一致

JSON的分类:
1、对象{ }
2、数组 [ ]

JSON中允许的值:字符串、数值、布尔值、null、对象、数组

将JSON字符串转换为JS中的对象:
在JS中,提供了一个工具类叫JSON,这个对象可以将一个JSON转换为JS对象,也可以将一个JS对象转换为JSON

JSON.parse():可以将JSON字符串转换为JS对象。他需要一个JSON字符串作为参数

JSON.stringify():可以将JS对象转换为JSON字符串,需要一个JS对象作为参数

eval():这个函数可以用来执行一段字符串形式的JS代码,并将执行结果返回。如果这个字符串中含有{ },它会将{ }当成是代码块,如果不想当成代码块,需要将字符串前后各加“()”。尽量在开发中不要使用,首先它的执行性能比较差,还有安全隐患。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值