JavaScript入门

HelloWorld与控制台

<body>
<!--Hello World!-->

<script type="text/javascript">
    alert("Hello World!")
</script>

</body>

html的body或head标签里面写<script type="text/javascript"></script>标签就能写JS语句,

alert是弹窗显示内容,运行时可以在浏览器右键审查元素,里面有控制台,一般在这里调试。

控制台可以用console.log(‘hello’)来打印结果。

数据类型

基本数据类型:

  1. Number - - (数字)
  2. String - - (字符串)
  3. Boolean - - (布尔值)
  4. Undefined - - (未定义)
  5. Null - - (空的)(其实是对象)
  6. Symbol - - (符号)

引用数据类型:

  1. Object - - (对象),以下都是属于Object之内的:
  2. Array - - (数组)
  3. Function - - (函数)
  4. Date - - (时间)
  5. RegExp - - (正则)
  6. …(还有很多)

定义一般用var,ES6可以用let,常量用const。

typeof NaN
'number'
typeof '123'
'string'
typeof true
'boolean'
typeof undefined
'undefined'
typeof null
'object'
typeof [1,2,3]
'object'
typeof Math.abs
'function'
typeof Math.abs()
'number'

String

console.log('a')  //单引号双引号都行
console.log('\'a\'')  //转义字符打出引号
console.log(`
多行
字符串
输出
`)  //飘号``输出多行字符串
var name='小明'
console.log(`名字是:${name}`)  //飘号输出模板字符串

var msg = 'Hello'
console.log(msg)
console.log(msg.length)
console.log(msg.toUpperCase())
console.log(msg.toLowerCase())
console.log(msg.indexOf('l')) //获取字符在字符串中的位置
console.log(msg.substring(2,4))
console.log(msg[0]) //可以通过字符串点调用方法,通过下标取字符串的元素
//注意字符串是不可变的,不能用下标赋值

数组

JS的数组可以包含任意数据类型。

  var arr = [2,4,6,8]
  console.log(arr)
  console.log(arr.length)
  arr[5] = 10    //数组自动变长
  console.log(arr.length)
  console.log(arr.indexOf(2))
  console.log(arr.slice(1,5))   //截取数组输出新数组

  console.log(arr.pop())
  arr.push(1)   //插入尾部
  console.log(arr)
  console.log(arr.shift())
  arr.unshift(3)  //插入头部
  console.log(arr)

排序、拼接:

let arr = [5,3,7,9,1]
console.log(arr.sort())
console.log(arr.reverse())
console.log(arr.concat('A','B','C'))
console.log(arr.join('-'))  //打印数组,用字符拼接

排序会改变数组本身,concat不改变。

对象

JS的对象相当于一组键值对。

键都是字符串,值是任意对象。

let person = {
  name: 'rosemary',
  age:23
}
console.log(person)
console.log(person.haha)  //不存在的属性不会报错,只会undefined
delete person.name   //可以动态地删除属性
console.log(person)
person.haha = 'haha'  //添加属性
console.log(person['haha'])   //下标方式取属性

分支与循环语句

与Java很像。if分支:

let age = 11;
if(age <= 3){
  alert('cry!!')
}else if(age <= 10){
  alert('haha!')
}else {
  alert('sad')
}

循环:

  • while
  • do while
  • for
  • forEach
  • for in
  • for of

while循环:(do while 跟Java也是一样的)

while (age<100){
    age++;
}

for循环:

for (let i = 0; i < 10; i++) {
    console.log(i)
}

forEach循环:

  let arr = [15,25,35]
  arr.forEach(function (value) {
      console.log(value)
  })

for in循环:

for (let num in arr){
    console.log(arr[num])
}

这里的num取到的是下标。

for of循环:

for (let num of arr){
    console.log(num)
}

这里的num取到的是具体的值。

Map和Set集合

ES6的新特性。

Map:

  let map = new Map([['tom',100],['jerry',90],['rose',80]]);
  alert(map.get('rose'))  //输出80,就是用键取值

  for (let i of map){   //for of 遍历键与值
    alert(i)
  }

  map.set('admin',70)
  map.delete('tom')
  console.log(map)

Set:无序且去重的集合

  let set = new Set([3,1,1,1])  //自动去重,相当于一个1
  console.log(set)

  for (let i of set){   //for of 遍历键与值
    console.log(i)
  }

  set.add(4)  //添加值
  console.log(set.has(4))   //判断set中是否包含某元素,返回布尔值

函数定义和参数获取

由于JS的弱类型特性,定义函数的时候不需要声明数据类型。

function abs(x){
  if (x<0){
    return -x;
  }else {
    return x;
  }
}
alert(abs(-3))

返回就是直接return,不需要事先声明。

如果没有return,执行完也会返回结果,即undefined。

JS中的函数可以传送任意个参数,且不存在重载。

试执行alert(abs()),返回undefined,如何规避调用者不传参数呢:

function abs(x){
  if(typeof x !== "number"){
    throw 'not a number!'
  }
  if (x<0){
    return -x;
  }else {
    return x;
  }
}
alert(abs())

这样可以在控制台抛出not a number!

此外可以用arguments获取参数,arguments相当于一个实参的数组。

function print() {
  for (let i = 0; i < arguments.length; i++) {
    console.log(arguments[i])
  }
}
print(1,2,3,5)

通过遍历arguments,打印出了传入的每一个参数。

ES6新特性:…rest

function print2(x,...rest) {
  for (let i = 0; i < rest.length; i++) {
    console.log(rest[i])
  }
}
print2(1,2,3,5)

传入参数的时候,最后加一个参数叫做…rest,就可以将超出形参列表的参数作为数组放到rest中,

执行这段代码,只会打出2,3,5,因为1是形参列表中的x不在rest中。

变量的作用域

全局作用域:

  1. 全局作用域在页面打开时被创建,页面关闭时被销毁。
  2. 编写在script标签中的变量和函数,作用域为全局,在页面的任意位置都可以访问到。
  3. 在全局作用域中有全局对象window,代表一个浏览器窗口,由浏览器创建,可以直接调用。
  4. 全局作用域中声明的变量和函数会作为window对象的属性和方法保存。
  5. window对象的属性和方法可以直接调用,如window.an() 可以写为 an()。

函数作用域:

  1. 调用函数时,函数作用域被创建,函数执行完毕,函数作用域被销毁。
  2. 每调用一次函数就会创建一个新的函数作用域,他们之间是相互独立的。
  3. 在函数作用域中可以访问到全局作用域的变量,在函数外无法访问到函数作用域内的变量。
  4. 在函数作用域中访问变量、函数时,会先在自身作用域中寻找,若没有找到,则会到函数的上一级作用域中寻找,一直到全局作用域(类似于双亲委派机制)。
  5. 在函数作用域中也有声明提前的特性,对于变量和函数都起作用,此时函数作用域相当于一个小的全局作用域。
  6. 在函数作用域中,不使用变量关键字声明的变量,在赋值时会往上一级作用域寻找已经声明的同名变量,直到全局作用域时还没找到,则会成为window的属性。
  7. 在函数中定义形参,等同于声明变量。
an();
bn();
function an(){
  var s = 'an'
  console.log(s);
}
var bn = function() {
  console.log('bn')
}

这段代码中,an作为函数被声明,可以把调用写在声明前面。而bn作为变量被声明,要先声明完,后面才能调用(运行会报bn不是函数的错误)。(即声明提前。赋值不提前)

闭包:为了在全局使用函数作用域中的变量。

养成规范:所有的变量定义放在script标签或函数的头部。

块级作用域let

for (var i = 0; i < 5; i++) {
  console.log(i)
}
alert(i)

执行,alert出来的是5试将var改为let,则alert不出来并报i未定义,这就是块级作用域。

let关键字定义for后面的i时,旨在这次fori循环中有效,var则不然,所以推荐用let。

{
  let a = 10;
}
alert(a)

执行,保存,a未定义,吧alert移进花括号内则可以打出,let改为var也可以打出,

这意味着,花括号是let的作用边界。

常量const

const也是ES6才有的,用来定义常量,以前没有这个关键字,常量就靠变量名大写,大家约定俗成不去修改。

const PI = 3.14;
PI = 2;

这样直接爆红。

方法的定义与调用,及apply

let Rosemary = {
  name:'Rosemary',
  birth:1998,
  age: function () {
    let date = new Date();
    return date.getFullYear()-this.birth;
  }
}

控制台可以查看一下age,算出来是24,明年就不同了。这里this指向的显然是Rosemary对象。

可以把方法写在外面:

function getAge() {
  let date = new Date();
  return date.getFullYear()-this.birth;
}
let Rosemary = {
  name:'Rosemary',
  birth:1998,
  age: getAge
}
alert(Rosemary.age())

这样仍能得到24,不会报错(调用方法时加括号就报错了)。

如果在Rosemary之外调用,如alert(getAge()),则打不出来,因为this指向的是window,而window中没有birth属性。这时可以用apply改变this的指向:

alert(getAge.apply(Rosemary))

这样就是24了。

Date日期对象

let now = new Date()
now.getFullYear()   //年
now.getMonth()   //月(0~11)
now.getDate()   //日
now.getDay()   //星期几
now.getHours()   //时
now.getMinutes()   //分
now.getSeconds()   //秒
now.getTime()   //时间戳
console.log(new Date(1664334733061))    //根据时间戳返回当前的时间
console.log(now.toLocaleString())   //转换为当前本地时间

JSON对象

Json即:JavaScript Object Notation(JavaScript 对象表示法)

JSON 是存储和交换文本信息的语法,类似 XML。

JSON 比 XML 更小、更快,更易解析。

JSON 易于人阅读和编写。

C、Python、C++、Java、PHP、Go等编程语言都支持 JSON。

例如:

{
    "sites": [
    { "name":"菜鸟教程" , "url":"www.runoob.com" }, 
    { "name":"google" , "url":"www.google.com" }, 
    { "name":"微博" , "url":"www.weibo.com" }
    ]
}

这个 sites 对象是包含 3 个站点记录(对象)的数组。

(还有个叫BSON的,是二进制的JSON,主要用在MongoDB)

打开搜索引擎——审查元素——网络——suggest?callback——响应,就能看到json:

在这里插入图片描述

在JavaScript中,一切皆为对象,任何JS支持的数据类型都可以用json来表示。

JSON 语法是 JavaScript 对象表示语法的子集:

  • 数据在键值对中
  • 数据由逗号 , 分隔
  • 使用斜杆 \ 来转义字符
  • 大括号 {} 保存对象
  • 中括号 [] 保存数组,数组可以包含多个对象

JSON字符串 和 JS对象 的转化:

let user = {
  name:'chan',
  gender:'male',
  age:'23'
}

let JasonUser = JSON.stringify(user)
console.log(user)
console.log(JasonUser)

打出user和JsonUser,发现user是JS里的对象,可以展开;

而JsonUser是字符串形式的对象。

再逆转化一下:

console.log(JSON.parse('{"name":"chan","gender":"male","age":"23"}'))

这样输出的就是对象了,和user无异。

原型继承与class继承

JS以前没有class继承,都是用原型来实现继承的:

let student = {
  name:'学生',
  study:function (){
    console.log(this.name + 'study...')
  }
}

let xiaoming = {
  name:'小明'
}

在这里,小明不能使用学生的study方法,因为没有继承。

使用原型继承,只需要加一句声明:

xiaoming.__proto__ = student

小明就能study了。但很显然,这个原型是可以动态改变的,跟java的父类不一样。

为了好看一点,ES6引入了class继承。

class student{
    constructor(name) {
        this.name = name
    }
    study(){
        console.log(this.name + 'study')
    }
}

let xiaoming = new student('小明')
xiaoming.study()

这是定义了学生类,再实例化了一个小明,下面写一个小学生继承一下学生类:

class pupil extends student{
    constructor(name,grade) {
        super(name);
        this.grade = grade
    }
    say(){
        console.log('我叫' + this.name + ',今年' + this.grade + '年级了')
    }
}

let xiaohua = new pupil('小花',3)
xiaohua.say()

console.log一下小花,发现这种继承仍然是通过原型实现的。

pupil的原型是student,student的原型是Object,Object的原型继续指向Object,这就是原型链。

Document对象模型(DOM)

BOM对象

BOM对象:Browser Object Model

DOM对象:Document Object Model

Browser就是浏览器,JavaScript的诞生就是为了在浏览器中运行。

浏览器(内核):

  • IE6~11
  • Chrome
  • safari(苹果)
  • FireFox(Linux)

第三方(内核是可选的):

  • QQ浏览器
  • 360浏览器

window对象代表浏览器窗口。

例如alert方法,本质是window.alert,是在window中的。

console.log(location)

location指向当前页面的url信息。

//主机
host: "localhost:63342"
//当前指向位置
href: "http://localhost:63342/webdemo/JS2/Demo18.html?_ijt=uf3auigeo19mgc2slo3jmhpup0"
//设置新的地址
assign('https://www.baidu.com/'

history代表浏览器的历史记录,可以点back后退,点forward前进。

获得DOM节点

对DOM的操作主要有:

  • 获得DOM节点
  • 更新DOM节点
  • 删除DOM节点
  • 增加DOM节点

html页面相当于一个DOM树形结构。几种常用的获得DOM节点的方法:

  • getElementsByTagName()
  • getElementById()
  • getElementsByClassName()
  • getElementsByName()
  <div id="father">
    <h1>标题1</h1>
    <p id="p1">p1</p>
    <p class="p2">p2</p>
  </div>

<script type="text/javascript">

  let h1 = document.getElementsByTagName('h1')
  let p1 = document.getElementById('p1')
  let p2 = document.getElementsByClassName('p2')
  let father = document.getElementById('father')
  let children = father.children     //获取父节点下所有的子节点
  // father.firstChild
  // father.lastChild

  console.log(h1)
  console.log(p1)
  console.log(p2)
  console.log(father)
  console.log(children)

</script>

这是原生代码,之后可以使用jQuery。

更新DOM节点

<div id="id1"></div>

<script type="text/javascript">
  let id1 = document.getElementById('id1')
  id1.innerText = '123'   //修改文本
  id1.innerHTML = '<strong>123</strong>'    //超文本,可以加html标签

  //修改CSS样式
  id1.style.color = 'red'   //修改颜色
  id1.style.fontSize = '100px'  //字体大小
</script>

实操一下,打开百度首页的控制台,执行两条指令:

let ss = document.getElementById('su')
undefined
ss.style.backgroundColor = 'violet'
"violet"

紫色百度就出来了:

在这里插入图片描述

注意更新节点的属性全部用引号包裹。

删除DOM节点

删除节点的逻辑:获得节点的父节点,通过父节点删除。

<div id="father">
  <p id="p1">长子</p>
  <p id="p2">次子</p>
  <p id="p3">幼子</p>
</div>

<script type="text/javascript">
  
let self = document.getElementById('p1')
let father = document.getElementById('father')
// self.remove()
father.removeChild(self)    //删除指定子节点
father.children[0].remove();    //删除下标为0的子节点

</script>

获得父节点的方法:parentElement

删除子节点的方法:removeChild

删除自己的方法:remove。这样好像不用父节点也能删啊。。。

上面代码运行后就只会打出幼子,长子和次子已被删除。

创建与插入DOM节点

如果我们获得了一个空节点,innerHTML就可以设置节点了,但如果这个节点不是空的,

原来的内容就会被覆盖。

本节目录:

  • 移动节点
  • 创建节点
  • 创建script标签节点
  • 获取body标签节点
  • 插入节点

移动节点:

<p id="js">JavaScript</p>
  <div id="list">
    <p id="se">JavaSE</p>
    <p id="ee">JavaEE</p>
  </div>

<script type="text/javascript">

  let js = document.getElementById('js')
  let list = document.getElementById('list')
  list.appendChild(js)

</script>

通过appendChild方法,js被移到了list中,原来位置的js就没了。

创建节点:

<div id="div"></div>

<script type="text/javascript">

  let newP = document.createElement('p')
  newP.id = 'newP'
  newP.innerText = '新标签'
  let list = document.getElementById('div')
  list.appendChild(newP)

</script>

通过createElement方法,创建一个新的节点。

创建script标签节点:

let myScript = document.createElement('script')
myScript.setAttribute('type','text/javascript')
myScript.innerText = 'alert(\'套娃\')'
list.appendChild(myScript)

相当于我们添加了一个script标签,并通过这个标签的innerText打出了‘套娃’。

打开浏览器控制台,打出list,看到我们创建在里面的两个标签:

<div id="div">
    <p id="newP">新标签</p>
    <script type="text/javascript">alert('套娃')</script>
</div>

注意setAttribute是万能方法,参数是键值对,同样可以用来设置id之类的。

获取body标签节点:

let body = document.getElementsByTagName('body')
body[0].style.backgroundColor = 'green'

可见body同样是可以进行DOM操作的。

这里需要注意,getElements的方法不同于getElement的方法,返回的是数组,所有body要加下标[0]。

可以获取body标签,就可以在body下面直接appendChild了。

插入节点:

<div id="list">
  <p id="A">A</p>
  <p id="B">B</p>
  <p id="C">C</p>
  <p id="D">D</p>
</div>

<script type="text/javascript">

  let aa = document.getElementById('A')
  let dd = document.getElementById('D')
  let list = document.getElementById('list')
  list.insertBefore(aa,dd)

</script>

本来四个p标签是ABCD排好序的,通过insertBefore方法,将A插到了D的前面,

执行以上代码,打出来的顺序是BCAD。

DOM表单操作

表单常见的节点:

  • 文本框
  • 下拉框
  • 单选框
  • 多选框
  • 隐藏域
  • 密码框
  • 等等。。。

表单的目的:提交信息。

简单的示例:

<form action="post">
  <p>
    <span>用户名:</span><input type="text" id="username">
  </p>
  <p>
    <span>性别:</span>
    <input type="radio" name="gender" value="male"><input type="radio" name="gender" value="female"></p>
</form>

<script type="text/javascript">

  let username = document.getElementById('username')
  let male = document.getElementsByName('gender')[0]
  let female = document.getElementsByName('gender')[1]
  
</script>

可以用male.checked查看是否选中了性别男。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值