JavaEE03_JavaScript

JavaEE03_JavaScript

1、使用javascript

1.1 js引入

Javascript代码写在script标签内,且script标签s必须成对出现,不能自闭和,不然会出错

<script type="text/javascript">script>

引入外部 文件名.js代码(src后跟路径)

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

1.2 基本语法

语法基本与java一致,不过js的变量只有var和let

var是全局bianl

let是局部变量

可以通过console.log()在浏览器控制台输出(浏览器F12)

alert()弹出弹窗

var的基本测试

/*** 基本类型var:*    1.number:js不区分小数和整数*              123   整数123*              123.1 浮点数123.1*              1.123e3  科学计数法*              -99    负数*              NaN    not a number*              Infinity  表示无限大*     2.字符串:'abc'  "abc"*     3.布尔值:true false(与java用法一样)*     4.逻辑运算:&&*                ||*                !*     5.比较(重要)*      =      赋值*      ==     等于(类型不一样,值一样,也会判断为true)*      ===    绝对等于(类型一样,值一样才会判断为true)*      避免使用==,容易出问题*     6.NaN  与所有数值都不相等,包括自身*     只能通过NisNaN(NaN)来判断这个数是否为NaN**     7.浮点数问题*      console.log((1/3)===(1-2/3));    因为精度会缺失,所以输出falseconsole.log(Math.abs((1/3)-(1-2/3))<0.00000001); 精度小于0.00000001,默认两个相等*     8.null和undefined*       null 空*       undefined 未定义*     9.数组:java必须是一系列相同类型的对象,在JS中并不需要这样,因为var是所有类型,如果越界就会undefined*     var arr=[1,2,3,4,'name',true,null];*     console.log(arr[1]);*     10.对象:对象是大括号,数组是中括号*     每个属性之间使用逗号隔开,最后一个不需要添加*     输出:person.name*/

1.3严格检查模式

<script>'use strict'
script>

前提:IDEA 需要设置支持ES6语法

‘use strict’ 严格检查模式,预防js的随意性导致产生的一些问题,比如直接写i=1;没有去定义它为 var或let也是可以使用的,且默认是var

必须写在javascript的第一行

2、js详解

2.1字符串

  • 正常字符串一般使用单引号或双引号包裹。

  • 转义字符:

/**** 2、转义字符*    \'*    \n*    \t*    \u4e2d    // \u#### Unicode编码*    \x41      //ascll**/
console.log('a\'');
console.log("a\nd");
console.log("\u4e2d\n\x41");
  • 多行字符串编写(tab上面的 ` 键)

    let msg= `
    xiaosi
    world
    `
    console.log(msg)
    
  • 模板字符串

    let name="xiaosi";
    let  msg2=`你好,${name}`
    
  • 字符串长度:.length

  • 字符串的不可变性

    var myStr = "Bob";
    myStr[0] = "J";//这是无法实现的,字符串创建完单个值是无法改变的,要改变要重新给它赋一个值var myStr = "Bob";
    myStr = "Job";
    
  • 大小写转换

    .toUpperCase()转大写

    .toLowerCase()转小写

  • 显示某字符的下标

    .indexOf(’ ')

  • substring

    .substring(n,m) 从第n个字符串截取到最后m个字符串,若m没写就是到最后一个字符串[n,m)

2.2 数组

  • 长度:给arr.length赋值,数组大小就会发生变化,自动添加undefined,如果赋值过小,元素就会丢失

    arr.length=10;
    
  • indexOf,通过元素获得下标索引,字符串的"1"和数字的1是不一样的,字符串的"1"是获取此字符串的下标值,1是获取下标1的字符串

  • slice()截取Array的一部分,返回一个新数组,类似String中的substring

    数组.slice(n) :从下标n开始截取,到最后一个字符,且原数组不会发生改变

  • push pop

    arr2.push("a","b");//压入尾部
    console.log(arr2);
    arr2.pop();//弹出尾部
    console.log(arr2);
    
  • unshift() shift()

    arr2.unshift("a","b");//压入头部
    console.log(arr2);
    arr2.shift();//弹出头部
    console.log(arr2);
    
  • 排序sort()

    sort() 方法用于对数组的元素进行排序。

    排序顺序可以是字母或数字,并按升序或降序。

    默认排序顺序为按字母升序。

  • 元素反转

    .reverse()

  • 拼接 concat,并没有修改数组,只是会返回一个新的数组

    arr3.concat(arr2)  //不会改变原数组
    
  • 连接符join,打印拼接数组,使用特定的字符串连接

    console.log(arr3.join('-'));
    //结果C-B-A
    
  • 多维数组

    let  arr4=[ [1,2],[3,4],["5","6"] ];
    console.log(arr4[1][1]);
    

2.3 对象

var 对象名={

​ 属性名:属性值,

​ 属性名:属性值

}

var person={//多个属性用逗号隔开,最后一个不加逗号name:'xiaosi',age:3,email:"1170035083@qq.com",score:0}
//对象赋值
person.name='haishi';
//使用一个不存在的对象属性,不会报错,会undefined
console.log(person.haha);
//动态删除属性,通过delete删除对象属性,可以在控制台直接删除
delete person.score;
//动态添加,直接给新的属性添加值就可以
person.haha="haha";
//判断属性值是否在对象中   xxx in xxx
console.log('name' in person);
console.log('toString' in person);//true 可以知道它父类的方法
//判断一个属性是否是这个对象自身拥有的hasOwnProperty
console.log(person.hasOwnProperty('name'));//true
console.log(person.hasOwnProperty('toString'));//false

Object的hasOwnProperty()方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。

pereson里面有name属性,虽然他的父类有toString但是他自己没有,所以是false

2.4 流程控制

除了foreach,其余的与java一致

//判断
var age=3;if(age>3){alert("haha");}else{alert("kuwa");}
//循环
while(age<100){age++;console.log(age);
}
//for循环
for(let i=100;i<110;i++){console.log(i);
}
//foreach循环,对象可以value.xxx
var arr=[1,2,3,34,54,6,7,12,32];
arr.forEach(function (value) {console.log(value);
})
/*
* 在java中,for(Type str:el){}
* */

2.5 Map和Set

与java一致

//ES6的新特性
//学生的成绩,学生的名字
var map=new Map([['tom',100],['jack',90],['haha',80]]);
var name=map.get('tom');
console.log(name);
map.set('admin',10);
console.log(map);
map.delete('tom');var set=new Set([3,1,1,1,1]);//set可以去重
set.add(2);
console.log(set);
set.delete(1);
console.log(set);
console.log(set.has(3));//里面是否包含x

2.6 iterator

// for in只能打印下标,新增下标不能正常显示下标,会直接显示里面的值
//若for in要打印数值的话,用下面实现
for(var num in arr){console.log(arr[num]);//这里的num只是下标
}//通过for of来打印数 遍历map 遍历set都是一样的
for(let x of arr){console.log(x);
}

2.7 定义函数

//定义方式1:
//绝对值函数,一旦执行到return就表示函数结束,返回结果
//如果没有执行return,函数执行完也会返回结果,结果是undefined
function aaa(x) {if(x>=0){return x;}else{return -x;}
}
/定义方式2:(与上一种等效)
/*
* function(x) {...}是一个匿名函数,但是可以把结果赋值给abs,通过abs就可以调用函数
* */
var abs= function(x) {if(x>=0){return x;}else{return -x;}
}
/*** 参数问题:js可以传任意个参数,也可不传递参数* 参数进来是否存在  假设不存在参数,如何规避(手动抛出异常)* 运算数为数字 typeof(x) = "number"字符串 typeof(x) = "string"布尔值 typeof(x) = "boolean"对象,数组和null typeof(x) = "object"函数 typeof(x) = "function"*/
function abc(x) {if(typeof x!=='number'){throw 'Not a Number';}if(x>=0){return x;}else{return -x;}
}
/*** arguments是一个JS免费赠送的关键字,代表传递进来的参数,是一个数组* 问题:arguments包含所有的参数,有时想使用多余的参数来进行附加操作,需要排除已有的参数* 若传入多个参,这些参数就会被自动放入arguments数组中,可以直接从arguments中拿出来*/
function bbb(x) {console.log("x->"+x);for(let i=0;i<arguments.length;i++){console.log(arguments[i]);}if(x>=0){return x;}else{return -x;}
}

2.8 可变长参数

以前的写法:

//以前的写法,使用arguments来判断aaa()里到底输入了多少个值,因为js是一款极其不严谨的语言,就算你传入一
//百个值都不会报错。所以可以使用arguments来执行传入多参的方法
function aaa(a,b) {console.log("a=>"+a);console.log("b=>"+b);if(arguments.length>2){for(let i=2;i<arguments.length;i++){console.log(arguments[i]);}}
}

由于ES6引入的新特性,可以直接写可变长参数:

//现在
function bbb(a,b,...rest) {//rest只能写在最后面,必须用...标识console.log("a=>"+a);console.log("b=>"+b);console.log(rest);
}

2.9 变量的作用域

  1. 全局作用域:所有地方都可以访问
  2. 函数作用域:只能在函数内部访问

变量的声明:显示声明(var i=1;)和隐式声明(i=1;)

  • 在函数体中声明的变量,在函数体外不能使用,要用得使用闭包

  • 如果两个函数用了同一个变量名,只要在函数内部声明就不冲突

  • 内部函数成员可以访问外部函数,外部不能访问内部

  • 内部函数变量和外部函数变量重名的情况下,内部与外部重名的部分用内部的变量。。。。由内向外查找

  • 假设外部存在这个同名的函数变量,则内部函数会屏蔽外部函数的变量

2.10 作用域的提升

下面的定义的变量上面可以调用(作用域提升),但是仅仅只是提升作用域,它的赋值并不会被提升上去。

var x='x'+y;
console.log(x);
var y='y';//结果:xundefined,js的执行引擎,自动提升了y的声明但是不会提升变量y的赋值,在js建立之初就存在的//养成规范:所有的变量定义都放在函数的头部,不要乱放,便于代码维护

2.11 alert的一些方法

alert(a);
alert(window.a);//默认所有全局变量,都会自动绑定在Window对象上
window.alert(a);//alert()这个函数本身也是Window变量
//把alert方法赋予别的变量,原来的alert失效
var old_alert=window.alert; //把alert方法赋给一个变量,这个变量就有了alert的功能
old_alert('haishi');//重写alert方法
window.alert=function () {
};//恢复
window.alert=old_alert;

JS实际上只有一个全局作用域,任何变量(函数也可视为变量),假设没有在函数作用范围内找到,就会向外查找,

如果在全局作用域都没有找到,报错ReferenceError

2.12 自定义唯一全局变量

由于我们所有的全局变量都会绑定到我们的window上,如果不同的js文件使用了相同的全局变量,就会造成冲突。解决办法:自定义唯一全局变量,把自己的代码全部放入自己定义的唯一空间名字中,降低全局命名冲突的问题

//唯一全局变量
var XiaoSi={};//定义全局变量或方法
XiaoSi.name='xiaosi';
XiaoSi.add=function(a,b){return a + b ;
}

全局作用域冲突使用自定义全局变量来解决,而局部作用域冲突问题则使用let来解决。

2.13 常量

在ES6之前,定义常量:只有用全部大写字母命名的变量就是常量;建议不要修改这样的值,但实际上是可以随意修改的。ES6我们可以const来实现真正的常量(类似java的final)

const PI='3.14'; //只读变量
console.log(PI);
PI='3.1415';//报错Uncaught TypeError: invalid assignment to const 'PI'

2.14方法

方法就是把函数放在对象里面,对象只有两个东西:属性和方法

var xiaosi={name:'小厮',birth:1998,//方法age:function () {//今年-出生的年份var now=new Date().getFullYear();return now-this.birth;}
}

也可以在对象中引入外面的函数。

function getAge() {var now=new Date().getFullYear();return now-this.birth;
}
var xiaosi={name:'小厮',birth:1998,//引入外部函数的方法age:getAge
}

3、扩展

3.1 typeof

console.log(typeof 123); //查看后面的东西是什么类型的(这里是number)

3.2 Date

var now=new Date();
now.getFullYear();//年
now.getMonth();//月 0_11代表月
now.getDate();//日
now.getDay();//星期几
now.getHours();//时
now.getMinutes();//分
now.getSeconds();//秒now.getTime(); //时间戳  全世界统一  1970 1.1 0:00:00 毫秒数console.log(new Date(1578106175991));//把时间戳转换为时间
/*** 转换*/
now=new Date(1578106175991);
console.log(now.toLocaleString());//调用一个方法,而不是属性
//now.toGMTString()格林威治标准时间

3.3 Json

/*** JSON一种轻量级的数据交换格式* 具有层次结构** 在JS中一切都是对象、任何js支持的类型都可以用JSON来表示* 对象{}* 数组[]* 键值对key:value*/
//对象转化为json字符串
var JSONUser=JSON.stringify(user);//json字符串转化为对象,参数为JSON字符串
var obj=JSON.parse('{"name":"xiaosi","age":3,"sex":"男"}');

3.4 js的面对对象编程

/*** 类:模板* 对象:具体的实例** 但在JS中,需要换一下思路:* 原型:*/
var user={name:'xiaosi',age:3,run:function () {console.log(this.name+" run...");}
};var Bird={fly:function () {console.log(this.name+" fly...");}
};var xiaoming={name:'xiaoming'  //无法直接调用run方法,会报错
};/*
* 原型对象(实际上是继承)
* */
xiaoming.__proto__=user;//小明的原型是user,这是旧的方法,可以随意更换
xiaoming.run();
xiaoming.__proto__=Bird;
xiaoming.fly();

3.5 class的继承

在ES6之前无class关键字,所以要使用prototype往前面的函数添加新方法

prototype 属性使您有能力向对象添加属性和方法。

 function  Student(name) {this.name=name;}//给student新增一个方法,要么改它的方法,要不如下获得它的原型增加...ES6之前的原生方法,不用记Student.prototype.hello=function () {alert('hello')}
//ES6之后
//定义一个学生的类
class Student{constructor/*构造器关键字*/(name) {this.name=name;}hello(){alert('hello');}
}
var xiaoming=new Student('xiaoming');
xiaoming.hello();
console.log(xiaoming.name);/*** 继承*/class XiaoStudent extends Student{constructor(name,grade) {super(name);this.grade=grade;}myGrade(){alert('我是一个小学生');}
}var xiaohong=new XiaoStudent('xiaohong');
xiaohong.myGrade();
console.log(xiaohong);

3.6 原型与原型链

原型

在JavaScript中,每当定义一个函数数据类型(普通函数、类)时候,都会天生自带一个prototype属性,这个属性指向函数的原型对象,并且这个属性是一个对象数据类型的值。

让我们用一张图表示构造函数和实例原型之间的关系:

3174701-2dd95188a8f6b19e

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

原型链

  • 1.__proto__constructor

每一个对象数据类型(普通的对象、实例、prototype…)也天生自带一个属性__proto__,属性值是当前实例所属类的原型(prototype)。原型对象中有一个属性constructor, 它指向函数对象。

    function Person() {}var person = new Person()console.log(person.__proto__ === Person.prototype)//trueconsole.log(Person.prototype.constructor===Person)//true//顺便学习一个ES5的方法,可以获得对象的原型console.log(Object.getPrototypeOf(person) === Person.prototype) // true

3174701-9a3de0b501161c07

image

  • 2.何为原型链

在JavaScript中万物都是对象,对象和对象之间也有关系,并不是孤立存在的。对象之间的继承关系,在JavaScript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条,专业术语称之为原型链

举例说明:person → Person → Object ,普通人继承人类,人类继承对象类

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

我们可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性;使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true

    function Person() {}Person.prototype.a = 123;Person.prototype.sayHello = function () {alert("hello");};var person = new Person()console.log(person.a)//123console.log(person.hasOwnProperty('a'));//falseconsole.log('a'in person)//true

person实例中没有a这个属性,从 person 对象中找不到 a 属性就会从 person 的原型也就是 person.__proto__ ,也就是 Person.prototype中查找,很幸运地得到a的值为123。那假如 person.__proto__中也没有该属性,又该如何查找?

当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层Object为止。Object是JS中所有对象数据类型的基类(最顶层的类)在Object.prototype上没有__proto__这个属性。

console.log(Object.prototype.__proto__ === null) // true

3174701-18a76d28c0a9ea1b

4、BOM和DOM

DOM是一套操作HTML标签的API(接口/方法/属性)
BOM是一套操作浏览器的API(接口/方法/属性)

4.1 操作BOM对象

4.1.1 基本

BOM:浏览器对象模型
JS诞生就是为了能够让他在浏览器中运行

  • 浏览器内核:
    IE 6-11
    Chrome
    Safari
    FireFox(Linux默认)

  • 三方:
    QQ,360

  • window:
    window代表浏览器窗口

window.innerHeight;
window.innerWidth;
window.outerHeight;
window.outerWidth;//浏览器的内宽高和外宽高,调整浏览器会改变
  • Navigator封装了浏览器的信息:

    navigator.appName
    “Netscape”
    navigator.appVersion
    “5.0 (Windows)”
    navigator.userAgent
    “Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0”
    navigator.platform
    “Win32”

大多数时候不会使用navigator对象,因为会被人为修改
不建议使用这些属性来判断和编写代码(例如if(navigator.appName=‘xxx’)之类的)

window.navigator;
  • screen屏幕
screen.width;
screen.height;//像素
  • location
/*** location(重要)* 代表当前页面的URL信息* host: "localhost:63342"  主机* href: "http://localhost:63342/JavaScript/lesson04/1.%E6%93%8D%E4%BD…87%8D%E7%82%B9%EF%BC%89.html?_ijt=onret8mf0ch9jg9gjfsdsv9vjv"  当前指向网页* protocol: "http:"  协议* reload: reload()  重新加载网页*/
console.log(location);//设置新的地址,直接转到assign指向的网站
location.assign('https://www.baidu.com');

4.1.2 document

/***document代表当前页面, HTMl DOM树*/
var dl=document.getElementById('app');//获取具体的文档树节点/*** 获取cookie* 劫持cookie原理* 恶意人员:获取你的cookie上传到他的服务器** 服务器端可以设置cookie:httpOnly(只读)*/
console.log(document.cookie);

4.1.3 history

history代表浏览器的历史记录,不建议使用
history.back() //后退
history.forward() //前进

4.2 操作DOM对象

4.2.1 基本

DOM:文档对象模型

核心:
浏览器网页就是一个DOM树形结构
1.更新:更新DOM节点
2.遍历dom节点:得到DOM节点
3.删除:删除一个DOM节点
4.添加:添加一个新的节点
要操一个dom节点就必须获得这个dom节点

4.2.2 获得DOM节点

document

<body>
<div id="father">
<h1>标题一h1>
<p id="p1">p1p>
<p class="p2">p2p>
div>
<script>//对应CSS选择器,获得dom节点var h1=document.getElementsByTagName('h1');var p1=document.getElementById('p1');var p2=document.getElementsByClassName('p2');var father=document.getElementById('father');var childrens=father.children; //获取父节点下的所有子节点//father.firstChild第一个节点//father.lastChild最后一个节点//这是原生代码,之后尽量使用jQuery();script>
body>

4.2.3 更新节点

var id1=document.getElementById('id1');
id1.innerText='456';//修改文本的值
id1.innerHTML='456';//可以解析HTML文本标签//可以进行CSS操作,在网页上可以直接用JS进行修改界面
id1.style.color='yellow';
id1.style.fontSize='200px';//不支持-,用驼峰命名

4.2.4 删除节点

/*** 删除节点的步骤:先获取父节点,再通过父节点删除自己* 第一种标准流程*/
var self=document.getElementById('p1');
var father=self.parentElement;
//father.removeChild(self);/*** 方法2:通过下标移除,要注意删除多个节点的时候children是在时刻变化的*/
//father.removeChild(father.children[1]);//你删除完一后原来的2就变成一

4.2.5 插入节点

我们获得了某个Dom节点,假设这个Dom节点是空的,我们通过innerHTML就可以增加一个元素了,但是这个Dom节点已经存在元素了,我们就不能这么干,会覆盖,可以使用追加:append

varjs=document.getElementById('js'),//已存在的节点list=document.getElementById('list');
//list.appendChild(js);//控制台输入,id为js的标签会变为div的子标签
/*** 通过JS创建一个新的节点,实现插入*/
var newP=document.createElement('p');//创建一个新标签
newP.id='newP';//标签id设为newP
/*newP.id='newP';等价于newP.setAttribute('id','newP');*/
newP.innerText='xiaosi';
list.appendChild(newP);
/*** 创建一个标签节点* 
                    

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部