zl程序教程

您现在的位置是:首页 >  前端

当前栏目

JavaScript入门笔记

2023-06-13 09:15:12 时间

DOM

DOM(文档对象模型) 是浏览器对 html 文件的描述方式, DOM API是浏览器提供给JavaScript操作html页面内元素的方式。简而言之, 浏览器提供了一些内置函数来让我们操作页面(增删改查)

查找元素

// 查找元素使用document.querySelector函数
// 函数参数是一个选择器(和 CSS 选择器一样)
   
// 元素选择器
var div = document.querySelector('div')
   
// class 选择器, 用的是  .类名
var form = document.querySelector('.login-form')
   
// id 选择器, 用的是   #id
var user = document.querySelector('#id-input-username')

操作元素默认属性

获得特定属性值

var userValue = user.getAttribute('value')

设置特定属性值

user.setAttribute('value', '新用户名')

查询属性是否存在

log(user.hasAttributes())        // 查看元素是否有属性
log(user.hasAttribute('value'))  // 查看元素是否有特定属性

删除某个属性

user.removeAttribute('value')

获得所有属性

var attributes = user.attributes

操作元素

创建

// 用document.createElement函数创建一个元素
var button = document.createElement('button'); 
// 添加文本或者html
// 1.
button.innerHTML = '注册用户'
// 2.
button.insertAdjacentHTML('beforeend', '注册用户')

修改

var form = document.querySelector('.login-form')
form.appendChild(button)    // 用appendChild给一个元素添加子元素

删除

var pwd = document.querySelector('#id-input-password')
// 以下两种方法都可以删除元素
// 一种是自毁
pwd.remove()
// 一种是父节点删除子元素
form.removeChild(pwd)

事件

事件是用来处理响应的一个机制,这个响应可以来自于用户(点击, 鼠标移动, 滚动等), 也可以来自于浏览器

这里描述了js所有事件

添加事件监听

var loginBtn = document.querySelector('#id-button-login')
// 添加click事件
loginBtn.addEventListener('click', function(event) {
    console.log(event.target + '按下了')
})

事件委托

可以把事件绑定在父元素上, 然后在运行时检查触发事件的对象(event.target), 来处理对应的业务

事件冒泡

事件的响应像水泡一样上升至最顶级对象

当一个元素接收到事件的时候, 会把他接收到的事件传给自己的父级, 一直到window (注意这里传递的仅仅是事件, 并不传递所绑定的事件函数. 所以如果父级没有绑定事件函数, 就算传递了事件也不会有什么表现, 但事件确实传递了。)

// 阻止事件向上冒泡
// 1.
event.stopPropagation()
// 2.
event.cancelBubble = true

事件捕获

事件流描述的是从页面中接受事件的顺序,微软(IE)和网景(Netscape)开发团队提出了两个截然相反的事件流概念,IE的事件流是事件冒泡流(event bubbling),而Netscape的事件流是事件捕获流(event capturing)。

  1. addEventListener添加事件监听时不传第三个参数时, 默认为冒泡流
  2. addEventListener的第三个参数是useCapture, 传入true时采用事件捕获

localStorage(本地存储)

浏览器自带的功能, 可以用来存储字符串数据, 在浏览器关闭后依然存在, 不同页面拥有各自独立的localStorage

// 把数组写入localStorage
var save = function(array) {
    var s = JSON.stringify(array)     // JSON序列化
    localStorage.todos = s
}

// 读取localStorage中的数据并解析返回
var load = function() {
    var s = localStorage.todos        
    return JSON.parse(s)              // JSON反序列化
}

ajax

// 创建AJAX对象
var r = new XMLHttpRequest()
// 设置请求方法和请求地址
r.open('POST', '/login', true)
// 设置发送的数据的格式
r.setRequestHeader('Content-Type', 'application/json')
// 注册响应函数
r.onreadystatechange = function() {
    if (r.readyState === 4) {
        console.log('state change', r, r.status, r.response)
        var response = JSON.parse(r.response)
        console.log('response', response)
    } else {
        console.log('change')
    }
}
// 发送请求
var account = {
    username: 'username',
    password: '123',
}
var data = JSON.stringify(account)
r.send(data)

面向对象 (OO, Object Oriented)

定义类

// 声明类
var Student = function(name, age) {
    this.name = name
    this.age = age
}
// 增加方法
Student.prototype.print = function() {
    console.log(`${this.name} is ${this.age}`)
}

实例化对象

var s1 = new Student('caicai', 22)
s1.print()

常用组件

点击展开详情的菜单

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>点击展开的菜单</title>
    <style>
        .menu-content {
            height: 100px;
            width: 100px;
            border: 1px solid red;
        }

        .hide {
            display: none;
        }
    </style>
</head>
<body>
    <div class="menu">
        <button class="menu-toggle">点击展开</button>
        <div class="menu-content hide">详情</div>
    </div>
    <div class="menu">
        <button class="menu-toggle">点击展开</button>
        <div class="menu-content hide">详情</div>
    </div>
    <div class="menu">
        <button class="menu-toggle">点击展开</button>
        <div class="menu-content hide">详情</div>
    </div>
    
    <script src='1.js'></script>
</body>
</html>
var toggleClass = function(element, className) {
    if (element.classList.contains(className)) {
        element.classList.remove(className)
    } else {
        element.classList.add(className)
    }
}

var bindEventToggle = function() {
    var menus = document.querySelectorAll('.menu')
    for (var i = 0; i < menus.length; i++) {
        menus[i].addEventListener('click', function(event) {
            content = event.target.parentElement.querySelector('.menu-content')
            toggleClass(content, 'hide')
        })
    }
}

bindEventToggle()

鼠标划过菜单项高亮效果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>鼠标划过菜单项高亮效果</title>
    <style>
        .menu-item {
            width: 138px;
            height: 138px;
            opacity: 0.6;
        }
        .highlight {
            opacity: 1;
        }
    </style>
</head>
<body>
    <div class="menu">
        <div class="menu-item"><img src="1.jpg" ></div>
        <div class="menu-item"><img src="2.jpg" ></div>
        <div class="menu-item"><img src="3.jpg" ></div>

    </div>

    <script src='2.js'></script>
</body>
</html>
var bindEventHighlight = function() {
    var items = document.querySelectorAll('.menu-item')
    for (var i = 0; i < items.length; i++) {
        items[i].addEventListener('mouseenter', function(event) {
            event.target.classList.add('highlight')
        })

        items[i].addEventListener('mouseleave', function(event) {
            event.target.classList.remove('highlight')
        })
    }
}

bindEventHighlight()

轮播图

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>轮播图</title>
    <style>
        .slide-div {
            position: relative;
            height: 470px;
            width: 590px;
            margin: 0 auto;
        }
        .hide {
            display: none;
        }
        .show {
            display: inline-block;
        }
        .slide-button {
            /* 子元素绝对定位的参考对象是往上找到一个非static的元素, 一般使用子绝父相  */
            position: absolute;
        }
        .next {
            right: 0;
            top: 50%;
            transform: translateY(-50%);
        }
        .prev {
            left: 0;
            top: 50%;
            transform: translateY(-50%);
        }
        .indicators {
            position: absolute;
            right: 50%;
            bottom: 5px;
            transform: translateX(50%);
        }
        .indicator {
            display: inline-block;
            width: 10px;
            height: 10px;
            border-radius: 50%;
            background: white;
            margin-right: 5px;
        }
        .choose {
            background: black;
        }
    </style>
</head>
<body>
    <div class='slide-div' data-count='3' data-active='0'>
        <img id='id-img-0' class='hide show' src="1.jpg" height="470" width="590" >
        <img id='id-img-1' class='hide' src="2.jpg" height="470" width="590" >
        <img id='id-img-2' class='hide' src="3.jpg" height="470" width="590" >
        <button class='slide-button next'>下一张</button>
        <button class='slide-button prev'>上一张</button>

        <div class="indicators">
            <div id='id-indicator-0' class="indicator choose"></div>
            <div id='id-indicator-1' class="indicator"></div>
            <div id='id-indicator-2' class="indicator"></div>
        </div>
    </div>

    <script src='./3.js'></script>
</body>
</html>

var updateSlide = function(active_index) {
    var active_id = 'id-img-' + active_index
    // 隐藏当前img
    document.querySelector('.show').classList.remove('show')
    // 显示下一张img
    document.querySelector('#' + active_id).classList.add('show')
    // 隐藏当前indicator
    document.querySelector('.choose').classList.remove('choose')
    // 显示下一个indicator
    document.querySelector('#id-indicator-' + active_index).classList.add('choose')
}

var bindEventSlide = function() {
    var slide = document.querySelector('.slide-div')
    // 事件委托
    slide.addEventListener('click', function(event) {
        var classs = event.target.classList
        if (classs.contains('slide-button')) {
            var slide = event.target.parentElement
            // img数量
            var count = parseInt(slide.dataset.count)
            // 当前显示的img的index
            var active_index = parseInt(slide.dataset.active)
            // 计算下一张(或上一张)img的index
            active_index = classs.contains('next') ? (active_index + 1)  : (active_index - 1 + count)
            active_index = active_index % count
            // 改写data-active
            slide.dataset.active = String(active_index)
            // 更新显示
            updateSlide(active_index)
        }
    })
    // 定时器  3s
    window.setInterval(function() {
        document.querySelector('.next').click()
    }, 3000)
}

bindEventSlide()

ES6 (ECMAScript 6标准)

ECMAScript是一种语言标准,而JavaScript是网景公司对ECMAScript标准的一种实现 ECMAScript 6标准(简称ES6)已经在2015年6月正式发布

模板字符串

var className = 'center'
var text = 'hello world'
// 反引号`...`来表示多行字符串, 并支持自动替换字符串中${...}
var t = `
    <div class='${className}'>
    ${text}
    </div>
`

let

通过var定义的变量, 作用域是整个封闭函数. 而let定义的变量作用域在块中.

for (var i = 0; i < 3; i++) {
    // ...
}
// 输出结果: 3
console.log(i)
//  -------------------------------
for (let j = 0; j < 3; j++) {
    // ...
}
// 访问j, 报错
console.log(j)

const

相当于C++中的指针常量, 指向不可修改, 但可修改指向对象中的值

cpp

int * const num = &a;

js

const a = 1
a = 2 // 错误

// 下面的是修改指向对象中的值, 所以可行
const arr = [1, 2]
arr.push(3)
// arr: [1, 2, 3]

Set

使用方法和array相似, 但set的元素不重复

var s = new Set()

// add方法添加元素, 和push一样
s.add(1)
s.add(2)

// has方法检查元素是否在set中
s.has(1) // true
s.has(3) // false

// size属性相当于length
s.size  // 2

// delete方法删除一个元素
s.delete(1)
s.has(1)

s.size  // 1

Map

js默认的object表示方法{}相当于java中的HashMap之类的数据结构, 即键值对. 但与java的HashMap不同之处在于, js对象的键必须是字符串. 为了解决这个问题, ES6中引入了Map数据类型. Map和Object相似, 在python中有dict和object两种数据结构, js在ES6也有独立的dict(Map).

// Map
var m = new Map()

// set方法增加一个值
m.set('name', 'cai')

// get方法得到一个值
m.get('name')
// -------------------------------------------------------------
// object
let o = {}

// set
o.name = 'cai'

// get
o.name

…(扩展符号)

作用是把数组解开成单独的元素

var a1 = [1, 2, 3]
var a2 = [...a1, 4]
// 结果是 [1, 2, 3, 4]

// ...可以用来传参
var a1 = [1, 2, 3]
log(...a1)
// 相当于log(1, 2, 3)
// 类似于log.apply(window, a1)

// 可变参数
// 用 ... 语法可以实现可变长度的参数, 多余的参数会被放进 args 数组中
var foo = function(a, ...args) {
   log(a, args.length)
}
foo(1, 2, 3, 4)

解构赋值

python中拥有的特性

// a, b分别被赋值为1, 2
var [a, b] = [1, 2]

// 相当于下面的代码
var arr = [1, 2]
var a = arr[0]
var b = arr[1]

// swap a and b
[a, b] = [b, a]

函数默认参数

大部分高级语言拥有的特性, 参数缺省

var fun = function(a, name='cai') {
    log(a, name)
}

箭头函数(Lambda表达式)

匿名函数定义的简化版本

语法

() => { 多条语句 }
(参数1, 参数2) => { 多条语 句 }  
(参数1, 参数2) => 单条语句
// 上面等价于下面定义
function(参数1, 参数2) {
    return 语句
}

例子

var a1 = [1, 2, 3]
var a2 = a1.map( n => n * n )
// 等价于
var a2 = a1.map(function(n) {
    return n * n
})

BOM

BOM(browser object model) 包含5个内容

  • location 管理 URL
  • navigator 管理浏览器
  • history 管理历史记录
  • screen 管理屏幕
  • window 管理浏览器所有的东西

location

location对象用来管理url的

// www.taobao.com页面的location对象的属性及方法
ancestorOrigins: DOMStringList {length: 0}
assign: ƒ ()
hash: ""
host: "www.taobao.com"
hostname: "www.taobao.com"
href: "https://www.taobao.com/"    // 改变href就可以跳转页面
origin: "https://www.taobao.com"
pathname: "/"
port: ""
protocol: "https:"  
reload: ƒ reload()        // 该方法用来刷新当前页面 
replace: ƒ ()             // 该方法用来替换当前页面, 参数为url
search: ""
toString: ƒ toString()
valueOf: ƒ valueOf()
Symbol(Symbol.toPrimitive): undefined
__proto__: Location

navigator对象是用来查询浏览器的信息的, 比如当前的操作系统平台, 浏览器型号厂商等

// navigator.userAgent的值
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36"
// navigator.platform的值
"MacIntel"

history

history对象是用来处理历史记录的

history.length      // 历史列表中的 url 数量

history.back()      // 相当于点击后退按钮
history.forward()   // 相当于点前进
history.go(-2)      // 相当于点击两次后退按钮

/*
 * 三个参数依次为: state, title, url
 * state: 一个与指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数。不需要则可以传null
 * title: 新页面的标题,但是所有浏览器目前都忽略这个值, 故可以传null  (可以设置document.title代替)
 * url:   新的网址,必须与当前页面处在同一个域, 
 */
history.pushState(null, 'title', '/profile')

// 用户点击前进或后退按钮时会触发window的popstate事件
window.addEventListener("popstate", function(event) {
    // state就是pushState的第一个参数
    var state = event.state;
    console.log('pop state', state)
})

// 作用和参数都和pushState相同, 但不生成一条历史记录
history.replaceState(null, 'title', '/profile')

strict模式

js在设计之初, 并不强制要求用var声明变量, 未用var声明的变量作为全局变量, 用var声明的变量作用域限制在函数体内 为了修补js这一严重设计缺陷, ECMA在后续规范中推出了strict模式, 在strict模式下运行的js代码, 强制通过var声明变量,未用var声明变量就使用的, 将导致运行错误 启用strict模式的方法是在js文件中第一行写上

'use strict'

注意: 浏览器内嵌的开发者工具的控制台可能不支持strict模式

本文作者: Ifan Tsai  (菜菜) 本文链接: https://www.caiyifan.cn/p/9271.html 版权声明: 本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!