复习js部分(每日更新)

1 篇文章 0 订阅

   函数
函数中,如果实参的个数和形参的一样,则输出正常。
函数中,如果实参的个数大于形参的个数,则会取到形参的个数的长度;

函数中,如果实参的个数小于形参的个数,则多的形参会定义为underfined;

函数的返回值:

function(){
    return 需要返回的结果
}

1、函数只是实现某种功能,最终的结果需要返回给函数的调用者;

2、只要函数遇到return,就把后边的结果,返回给函数的调用者;

function getResult(){
 return 666
}
getResult()   //等于是 getResult() = 666
function getMax(num1,num2){
    if(num1> num2){
        return num1;
    }else {
        return num2;    
    }
}
getMax(1,6)
//最终结果是返回的是6

利用函数算数组中的最大值:

function getArr(arr){
    let max = arr[0]
    for(let i =1;i<arr.length;i++){
        if(arr[i] > max){
            max = arr[i]
        }
    }
    return max

}
let max = getArr([1,2,3,5,6])
//最终结果是6

return 只能返回一个值,并且return后边的语句不执行。
如果不return返回值,则调用时的值就是underfined

 arguments的使用
 

function arr(){
    console.log(arguments); //会以假数组方式显示,
}
arr([1,2,3])

1、具有数组的length属性,

2、按照索引的方式进行存储

3、它没有真正数组的一些方法

(它是一个函数内置的)

函数有两种声明方式:

1、第一种是命名函数:

function fn(){}
fn()
2、匿名函数
var fun = function(){}
调用方式是fun()
注:此时的fun()是变量

作用域:

 分为两种:一种是全局作用域,另一种是局部作用域。
1、全局作用域就是整个script标签,或者一个单独的js文件。
2、局部作用域(函数作用域),在函数内部就是局部作用域,

作用域链:内部函数访问外部函数的变量,采取的就是查找的方式来决定取哪个值,这样的结构称为“作用域链”,就近原则。

let Num = 10;
function fn(){
    let Num = 20;
    function fun() {
        console.log(Num);
    }
}

打印输出结果为:20,就近原则

JS引擎运行js分为两部:
1

(1)、预解析:js引擎会把js里边的var 还有 function提升到当前作用域的最前边;

(2)、顺序执行,按照书写顺序从上往下执行;

2、

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

(1)、变量提升就是把所有的变量声明提升到当前作用域最前边,赋值的不提升;

(2)、函数提升就是把所有的函数声明提升到当前作用域的最前边,不调用函数

对象

对象就是一个具体的事物;在js中对象就是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串,数值,数组等;

对象是由属性和方法组成

属性:就是事物的特征,在对象中用属性来表示;

方法:事物的行为,在对象中用方法来表示;

创建对象的三种方法:

一、利用字面量创建对象
 

let obj = {
        uname: 'abc',
        age: 20,
        sayHi: function(){}
}

里边的属性采取键值对形式;

多个属性和方法之间用逗号隔开;

方法后边跟着是一个匿名函数;

1、使用对象属性:

对象.属性

2、使用对象方法:

对象.方法

二、变量、属性、方法、函数的区别

变量和属性:都是用来存放数据的

区别:

变量:单独声明并赋值,使用时候直接写变量名,单独存在;

属性:不需要单独声明,但是使用时必须是对象.属性

函数和方法:都是用来实现某种功能,做某件事

区别:

函数是单独声明的,并且调用时,函数名()

方法是在对象里边,使用时,对象.方法()

二、利用new object()创建对象

let obj = new Object();
obj.uname = 'aaa'
obj.age = 10
obj.sayHi = function(){}

调用时:

obj.sayHi();
obj.uname;

利用构造函数创建对象:

构造函数:

function 构造函数名(){
    this.属性 = 值
    this.方法 = function(){}

}
new 构造函数名()
function Star(uname, age, sex){
    this.name = uname
    this.age = age
    this.sex = sex
}
let a = new Star('姓名',30,'男')

1、构造函数名首字母大写;

2、构造函数不需要return,就可以返回结果

3、调用构造函数必须要有new

构造函数和对象的区别:

构造函数:泛指一大类;

对象:是一个具体的事物;

构造函数创建对象的执行过程为:

1、new 构造函数可以在内存中创建一个空对象,

2、this 指向这个空对象;

3、执行构造函数里边的代码,添加属性和方法

4、返回这个新对象,所以不需要在再外边return 了

如何遍历一个对象:

使用for......in

for(变量 in 对象){}

for(let i in obj){
    console.log(i); 
}

这样写时,遍历出来的是变量名

------------------------------------------------------------------
 

for(let j in obj){
    console.log(obj[j]);
}

当这样写时,输出的结果是属性值;

数组对象

数组去重

目标:把旧数组的里边不重复的元素选取出来,放到新的数组中,重复的去掉;

核心算法:遍历旧的数组,然后每遍历出来一个就拿这个去和新数组中的每一个进行查询,如果存在就不添加,反之添加;

(如果返回的是-1,表示没有)

function arr(arr) {
    var newArr = []
    for(let i =0;i<arr.length;i++){
       if(newArr.indexOf(arr[i]) === -1){
        newArr.push(arr[i]);
        }
    }
    return newArr
}

let ab = arr([11,2,11,3,5,6])

返回结果就是[11,2,3,5,6]

数组转字符串

 字符串对象
var str = ‘andy’

console.log(str.length)  会打印输出4

这样的过程就是基本包装类型:把简单的数据类型,包装成为复杂数据类型

相当于这样:

let temp = new String ('andy')  1、构造函数,把简单数据类型包装为复杂数据类型

str = temp  2、把临时变量值赋值给str

temp = null;    3、销毁这个临时变量

 基本包装类型类型:

一共有三种,分别是:String   Number     Boolean,把简单数据类型包装为复杂数据类型就可以拥有属性和方法。

字符串对象——字符串的不可变性

当改变字符串的变量时,实际上是又开辟了一个空间。

let ab = 'zifuchuan'
ab = 'zhi'

实际上是开辟了两个空间


字符串对象的——根据字符返回位置

1、indexOf('要查找的字符', 开始的位置): 返回指定内容在元字符串中的位置,如果找不到就是-1,找到就返回索引号。

2、lastIndexOf(): 从后往前找,只找第一个匹配的。

let str = 'obasdffbobaobadobaob'
let index = str.indexOf('o');
let num = 0
while(index !== -1){ 
    num ++;
    index = str.indexOf('o', index + 1)
}

字符串对象——根据位置返回字符

charAt:返回指定位置的字符(Index字符串的索引号)

let str = 'asdf'
for(let i =0;i<str.length;i++){
    console.log(charAt(i));
}

charCodeAt(index) :获取指定位置字符的ASCII 码,

例如:str.charCodeAt(0);  也就是 a ,a的ASCII码为97

str[index] 获取指定位置字符,str[0] ,a

案例:

let str = 'asdfsadf'
let obj = {}
for(let i = 0;i< str.length; i++){
    let chars = str.charAt(i); //根据位置返回字符
    if(obj[chars]){   //判断对象里是否已经存在这个属性
        obj[chars]++;   //如果已经存在就把它加1
    } else {      
        obj[chars] = 1;   //如果对象里边没有这个属性就赋值为1;
    }
    
}

现在对象obj里边存的是每个字符出现的次数,现在要算出最大值:

遍历对象for ......in

let maxNum = 0
let ch = ''
for (let a in obj){
    if(obj[a] > maxNum) {
        maxNum = obj[a]
        ch = a
    }
}
console.log(maxNum);  得到出现最多的次数
console.log(ch);   得到出现最多的属性名

字符串操作方法

concat(str1, str2) : concat()方法用于连接两个或者多个字符串。拼接字符串,等效于+

substr(start, length) :  从start 位置开始(索引号),length 取的个数。

slice(Starr,end) : 从start位置开始,一直截取到 end 位置,包括end 。

substring(start, end ) :  从 start 位置开始,截取到 end 位置,但是不包括end

replace('被替换的',  ' 替换为的字符') ,

split( '分隔符'  ) :  把字符串,从指定的分隔符分隔为几个数组,(join()把数组转换为字符串)

简单数据类型和复杂数据类型关系

1、简单数据类型
(1)、简单数据类型里边有一个特殊的null,它返回的是一个空对象object

堆和栈:

1、栈

简单数据类型存放到栈里边,在里边直接开辟一个空间存放值;

2、堆:

复杂数据类型存放在堆中,首先在栈中存放地址,用十六进制表示,然后这个地址指向堆中的数值;所以当改变堆中的数据是,由于指向的是同一个地址,所以值会发生改变;

获取特殊元素(body,html)

1、获取到body元素

document.body

2、获取到html元素,

document.documentElement

事件三要素:

分别是: 事件源,事件类型,处理程序

事件源:要触发的对象;

事件类型:单击,移动等;

处理程序:点击事件触发的逻辑;

事件基础:

innerHTML和innerText的区别:

1、innerText不识别html标签,并且去除换行和空格

2、innerHTML识别html标签

这两个属性是可读写的,可以获取元素里边的内容

 操作元素——表单

<button></button>
<input type = 'text' value = "请输入内容">
<script>
    let btn = document.querySelector('button');
    let ipt = document.querySelector('input');
    btn.onclick=function(){
        ipt.value = '修改了表变里边的input的值';
    }


</script>

注:在元素的事件中,this指向的是函数的调用者

let btn = document.querySelector('button');
let ipt = document.querySelector('input');
btn.onclick=function(){
    ipt.value = 'input的值发生变化'
    this.disabled = true    //此时this就是相当于btn这个按钮
}

在上边的实例中,this就是指向的btn。

操作元素——属性,样式

可以通过js修改元素的大小,颜色,位置等样式。

1、element.style     行内样式操作

let div = document.querySelector(div);
div.onclick = function(){
    this.style.backgroundColor = 'pink'
    this.style.width = '300px'
}

        里边的样式采取驼峰命名法,并且由于是使用的style行内样式权重较高。

2、element.className     类名样式操作:

.change{
 font-size: 25px
 color: white;
 margin-top: 10px

}

<div>使用element.className</div>
 
<script>
    let dv = document.querySelector('div');
    dv.onclick = function(){
        dv.className = 'change'
    }

</script>

注:如果样式较少或者功能简单,可以采用行内样式方式修改元素;
如果样式较多,情况下可以使用类名的方式;

由于class是一个保留字,所以类名是用的className 来操作;

className会直接更改元素的类名,会覆盖原来的类名;

如果想不替换原来的类名可以在添加类样式时,把原来的类名放在前边,空格后边加上新添加的类名。

操作元素总结:

操作元素内容:innerHTML

操作常见元素属性: src   href    title等

操作表单元素属性:    type      value    disabled等

操作元素样式属性:   element.style     className

排他思想:

<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
    let btns = document.getElementsByTagName('button');
    for(let i = 0;i<btns.length;i++){
        btn[i].onclick = function(){
            for(let j = 0;j<btns.length;j++){
                btns[j].style.backgroundColor = '';
            }
            btn[i].style.backgroundColor = 'pink'
        }

    }


</script>

表格隔行变色:

.bg{

    background-color: pink
}

<body>
    <table>
        <thead></thead>
        <tbody></tbody>
    </talbe>

    <script>
    //获取到所有的在tbody里边的行,tr
    let trs = document.querySelector('tbody').querySelectorAll('tr');
    //利用循环注册绑定事件
    for(let i = 0;i<trs.length;i++){
        trs[i].onmouseover= function(){
            this.className = 'bg'
        }
        trs[i].momouseout= function(){
            this.className = ''
        }
    }
    </script>

</body>

案例重点:全选,单选

首先:全选和取消全选的:

let chaAll = document.getElementById('chaAll');
let chas = document.getElementById('chas');
chaAll.onclick=function(){
 console.log(this.checked);   checked可以得到当前复选框的选中状态,选中就是true,反之false
    for(let i = 0;i<chas.length;i++){
        chas[i].checked = this.checked ; // 把当前全选状态赋值给下边遍历的字选项, 
    }
}

然后:下边子选项判断是否全部选中,给所有子选项绑定点击事件,每次点击都循环查看是否有选中的,如果有一个没有选中,则全选就不勾选;

let chaAll = document.getElementById('chaAll');
let chas = document.getElementById('chas');
chaAll.onclick=function(){
 console.log(this.checked);   checked可以得到当前复选框的选中状态,选中就是true,反之false
    for(let i = 0;i<chas.length;i++){
        chas[i].checked = this.checked ; // 把当前全选状态赋值给下边遍历的字选项, 
    }
}

for(let j = 0;j<chas.length;j++){
    chas[j].onclick=function(){
        let flag = true
       for(let i =0;i<chas.length;i++){
            if(!chas[i].checked){
                flag = false
                break;
            }
        }
        chall.checked = falg
    
    }
}

获取到元素:

可以通过document.querySelector,等方法获取到元素,并且可以通过使用

dir,打印输出元素的属性,方法,console.dir()

可以通过使用document.getElementByTagName('li')获取到元素,返回的是一个伪数组的对象集合(如果没有元素,返回的是一个空的伪数组)

如果需要获取到某个元素里边的元素,可以通过这样方式使用:

元素.getElementByTagName(),由于返回的是伪数组,所以需要指定索引号,指定元素;

获取元素的属性值:

有两种方式:1、可以通过element.属性  ,可以获取内置属性,自身自带属性;

   2、element.getAttribute('属性'),获取的自定义属性;

设置元素属性值:

(1)element.属性 = '值'

(2)element.setAttribute('属性', 值):    element.setAttribute('index', 2):

移除元素的属性值:

removeAttribute('属性'):  div.removeAttribute('index');

tab栏案例:

分析:1、tab栏切换有两个大模块

2、上边的选项卡,点击哪个,哪个样式就发生变化

3、下边的模块内容,会跟随上边的选项卡变化,所以下面的模块变化写到点击事件里边;

4、规律:下面的模块显示内容和上面的选项卡一一对应,相匹配。

5、核心思路:给上面的栏,每个添加一个自定义属性'inde',属性值从零开始

6、当我们点击上边的哪个栏的,就获取到当前点击的自定义index属性值,其他的隐藏;

let tabList = document.querySelector('.tab_list');
let lis = document.querySelector('li');
let items = document.querySelector('.item');
for循环绑定点击事件
for(let i = 0;i<tabList.length;i++){

    lis[i].setAttribute('index', i);

    lis[i].onclick=function(){
      for(let j=0;j<lis.length;j++){   //排它思想,清空其他的背景
        lis[j].className = ''
      }
      lis[i].className = 'current'     //给点击的设置背景

    2。下边显示内容模块
    let index = this.getAttribute('index');   //获取到当前点击的index属性值
    for(let i =0;i<item.length;i++){
        item[i].style.display = 'null'
    }
    item[index].style.display = 'block'

    }
    

}

H5自定义属性

自定义属性的目的:为了保存并使用数据,有些数据可以保存到页面中而不用保存到数据库中。

自定义属性是通过:getAttribute('属性')获取

但是有些自定义属性容易引起歧义,不容易判断是元素内置属性还是自定义属性。所以H5新添加了自定义属性。

H5规定,自定义属性要以  'data-'  作为开头并且赋值。

如:<div data-index = '1' > </div>

H5新增的获取自定义属性的方法:element.dataset.index 获取 element.dataset['index']

<div getTime="20" data-index = '2' data-list-name = 'andy'></div>
<script>
    let div = document.querySelector('div');
    console.log(div.getAttribute('getTime'));
    div.setAttribute('data-time', 20)
    h5新增的获取自定义属性的方法,它只能后去data-开头的
    dataset是一个集合里存放了所有以data开头的自定义属性
    console.log(div.dataset);
    如果自定义属性里边有多个 ‘-’ 链接的单词,我们获取的时候采取驼峰命名法。


</script>

节点操作:

获取节点通常两种方式:

1、利用DOM 提供的方法获取元素,

例如:document.querySelector,

        document.getElementById

document.getElementByTagName()

2、利用节点层级关系获取元素;

利用父子,兄弟节点获取元素

node.parentNode(获取到的是当前元素最近的父级元素)

节点概述:

一般节点至少拥有三个基本属性:nodeType节点类型;nodeName节点名称;nodeValue节点值

元素节点 nodeType为1

属性节点 nodeType 为 2

文本节点 nodeType 为 3 (空格,换行,文字等)

父节点操作parentNode:

<body>

<ul>
    父元素
    <li>子元素</li>

</ul>
<script>
let lis = document.querySelector('子节点');
console.log(lis.parentNode); 打印输出当前的lis的父节点;

</script>

</body>

注:就近原则。(只能获取到最近的父级节点)

子节点操作parentNode.childNodes

但是,此方式会获取到所有的节点,元素节点,属性节点,文本节点。


<ul>

<li></li>
</ul>

<script>
let uls = document.querySelector('ul');
for(let i =0;i<uls.childNodes.length;i++){
    if(uls.childNodes[i].nodeType ==1){
    console.log(uls.childNodes[i]);
    }
}

</script>

所以如果获取子元素节点可以使用:parentNode.children

是一个只读属性,返回所有的子元素节点。

获取到第一个子节点:parentNode.firstChild

但是此方法会获取到是包含,元素节点,属性节点,文本节点的第一个节点;

如果只获取到第一个子元素节点:parentNode.fristElementChild,

获取到最后一个子元素几点: parentNode.lastElementChild

实例:

let nav = document.querySelector('.nav');
let lis = nav.children;  //获取到下边的子元素节点
for(let i =0;i<lis.length;i++){
    lis[i].children[1].onmouseover=function(){
        this.children[1].style.display = 'block'
    }

    lis[i].children[1].onmouseout=function(){
        this.children[1].style.display = 'none'
    }
}

兄弟节点:

1、node.nextSibling:返回当前元素的下一个兄弟节点(包括元素节点,属性节点,文本节点),找不到则返回Null,同样包括全部的节点;

2、node.previousSibling :返回当前元素的上一个兄弟节点(包括元素节点,属性节点,文本节点),找不到则返回Null,也是返回全部的节点。

3、node.nextElementSibling: 返回当前元素的下一个元素节点,找不到返回Null;

4、node.previousElementSibling;返回当前元素的上一个元素节点,找不到返回Null

创建节点:

document.createElement('节点');

例如:document.createElement('li');


<ul></ul>


let li = document.createElement('li');
首先创建一个节点
let ul = document.querySelector('ul');
ul.appendChild(li); 创建的元素追加到当前元素里边。

  如果需要向页面前边追加一个新的元素:元素.insertBefore

节点案例:简单留言发布

let btn = document.querySelector('button');
let text = document.querySelector('textarea');
let ul = document.querySelector('ul');
btn.onclick=function(){
    if(text.value !==''){
        let li = document.createElement('li');
        li.innerHTML = text.value
        ul.insertBefore(li);
    } else{
        return
    }


}

删除节点:

node.removeChild(child) :这个方法是从DOM 中删除一个子节点,返回删除的节点

javascript:;禁止默认行为

let btn = document.querySelector('button');
let text = document.querySelector('textarea');
let ul = document.querySelector('ul');
btn.onclick=function(){
    if(text.value !==''){
        let li = document.createElement('li');
        li.innerHTML = text.value + "<a href='javascript:;'>删除</a>"
        ul.insertBefore(li, ul.children[0]);  把当前li追加到ul的第一个位置
        let as = document.querySelectorAll('a');
        for(let i =0;i<as.length;i++){
            as[i].onclick=function(){
                ul.removeChild(this.parentNode);
            }
        }
        


    } else{
        return
    }


}

克隆节点(赋值节点)

node.cloneNode( true| false):   方法返回调用该方法的节点的一个副本。也称为克隆节点/拷贝节点

如果为true:表示为深拷贝;

如果不添加或者为false,表示为浅拷贝;

深拷贝表示节点,内容都拷贝;

浅拷贝表示只拷贝节点;

案例动态生成表格:

<body>
    <table cellspacing="0">
        <thead>
            <tr>
                <th>name<th>
                <th>class<th>
                <th>age<th>
                <th>num<th>
            </tr>
        </thead>
        <tbody></tbody>
    </table>
    <script>
        let datas={
            [
            {
            name:'张三',
            class: '一般'
            age: 20    
            },
            {
            name:'张三',
            class: '一般'
            age: 20    
            },
            {  name:'张三',
            class: '一般'
            age: 20
            } 
            ]
        }
    let tbody = document.querySelector('tbody');
    for(let i=0;i<datas.length;i++){
        let tr = document.createElement('tr');
        tbody.appendChild(tr);
    //行里边创建单元格td,单元格的数量取决于每个对象里边的属性的个数,for...in...遍历出来对象
        for(let k in datas[i]){
       //创建节点td
            let tds = document.createElement('td');
            tds.innerHTML = data[i][k]
            tr.appendChild(td)
            //把对象里边的属性值 data[i][k]赋值给td
        }
        //创建删除的单元格
        let td = document.createElement('td');
        td.innerHTML = "<a href='javascript:;'></a>"
        向当前行里边追加删除单元格
        tr.appendChild(td)
        
    }

    点击删除,删除整行
        

    let as = document.querySelectorAll('a')
获取到所有的删除的a

    for(let i = 0;i<as.length;i++){    //遍历所有的啊,给每个添加点击事件
        as[i].onclick=function(){
           tbody.removeChild(this.parentNode.parentNode)     //移除节点,点击删除,它的父几点是单元格,单元格的父几点是行

        }
    }

    </script>
</body>

创建元素的三种方式:

1、document.write():如果页面文档流加载完毕后,在调用这段代码,会使得页面重绘;

2、document.innerHTML;

3、document.createElement();

document.innerHTML和document.createElemnet的区别:

document.innerHTML:如果采用拼接字符串的方式,效率会很低;但是如果采用先拼接到数组里,然后把这个数组用join()分隔为字符串就效率高;

document.createElement:  这样方式效率略低于innerHTML的数组方式,但是结构清晰。

DOM重点核心:

文档对象模型简称:DOM,是可扩展标记语言的编程接口;

 DOM操作主要针对元素的:增删改查;

创建 :document.write

          document.innerHTML

        document.createElement

增加:appchild        innerBefore

修改:

删除:removeChild

查询:

事件高级:

注册事件的两种方式:

传统注册事件:

1、onclick ,onmouseover等;

  事件侦听注册事件:

2、addEventListener

里面的事件类型是字符串,必定加引号,而且不带on,

同一个元素,同一个事件可以添加多个侦听器

let btns = document.querySelectorAll('button');
btns[0].addEventListener('click',function(){
    alert('弹出一个对话框');
})
btns[0].addEventListener('click',function(){
    alert('弹出一个对话框');
})

当点击按钮时可以先后弹出两个对话框

删除事件:

传统删除事件的方式:元素.事件名 = null

let divs = document.querySelector('div')
divs[0].onclick = function(){
    alert();
}
divs[0].onclick = null

事件侦听删除事件:

removeEventListener('事件名称', 函数)

divs[1].addEventListener('click', fun)   删除事件时候,就需要使用命名函数了

function fun(){
    alert();
    div[1].removeEventListener('click', fun);
}

DOM事件流

 DOM事件流分为三个阶段:1、捕获阶段  2、当前目标阶段  3、冒泡阶段

DOM 事件流在js代码中只能执行捕获或者冒泡其中一个阶段

onclick事件: 冒泡事件

在事件侦听中,addEventListener的第三个参数如果是true是捕获阶段,如果是false或者不写就是冒泡阶段

什么是事件对象?

event就是一个事件对象,元素.onclick = function(event){}

例如:div.onclick = function(event){}

事件对象就是我们事件的一系列的相关数据的集合,与事件相关,比如点击事件里边包含了与点击事件有关的信息,属性,方法;鼠标移动事件包含所有的和鼠标相关的属性和方法等。

这个事件对象可以自己命名,比如e;

事件对象常见的属性和方法:

1、e.target()返回触发事件的对象,div,span

2、e.type   返回事件的类型,click   ,mouseover

3、e.preventDefault()  阻止默认事件,比如不让链接跳转;

4、e.stopPropagation() 阻止事件的冒泡

e.target和this的区别

e.target返回的是触发事件的对象(元素),

this返回的是绑定事件的对象(元素)

阻止默认行为:preventDefualt()

<a href="#"></a>

let a = document.querySelector('a');

a.addEventListener('click', function(e){

        e.preventDefult();    //标准写法

})

阻止事件冒泡:stopPropagation()

事件委托:

事件冒泡本身特性,有时不需要冒泡,有时使用冒泡可以有很好的作用。

原理:

不单独给子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子阶段。

<body>

    <ul>
        <li>子节点</li>
        <li>子节点</li>
        <li>子节点</li>
    </ul>
    <script>
        
        //给父节点添加事件侦听器,利用事件冒泡给子节点添加。
        let ul = document.querySelector('ul')
        ul.addEventListener('click',function(){
            alert('点击子节点,根据点击冒泡,触发父节点事件');

        })
    </script>
</body>

鼠标事件对象

event对象代表事件的状态,跟事件相关的一些列信息的集合。

e.clientX :返回鼠标相对于浏览器窗口可视区的X坐标;

e.clientY : 返回鼠标相对于浏览器窗口可视区的Y坐标;

e.pageX: 返回鼠标相对于文档页面的X坐标

e.pageY : 返回鼠标相对于文档页面的Y坐标

e.screenX : 返回鼠标相对于电脑屏幕的X坐标;

e.screenY: 返回鼠标相对于电脑屏幕的Y坐标;

实例:

<img src='image.png'>
<script>
    let img = document.querySelector('img')
    document.addEventListener('mousemove', function(e){
         let x = e.pageX
         let y = e.pageY
        img.style.left = y + 'px'
        img.style.top = x + 'px'
    });


</script>

常用的键盘事件:

1、onkeyup(事件侦听:keyup) : 键盘按键松开时触发;

2、onkeydown(事件侦听:keydown):  键盘按钮按下时触发;

3、onkeypress(事件侦听:keypress): 键盘按键被按下时触发(但是不识别特殊功能键)

键盘事件对象:

keyCode:返回的是对应键盘的ASCII码值。

keyup 和 keydown 这两个事件,不区分字母大小写,即a和A 返回keyCode的值一样

<script>
    document.addEventListener('keyup', function(e){
        console.log(e.keyCode);
        
    });
    document.addEventListener('keydown',function(e){

        console.log(e.keyCode)
    })

</script>

但是keypress区分大小写:

A返回97

a返回65

document.addEventListener('keypress', function(e){
    console.log(e.keyCode)
})

案例按键按下指定键,页面有相应操作:

思路:首先判断是否按下的s键,如果按下的是s键光标定位在输入框;

然后:使用键盘事件对象的keyCode判断;

搜索框获得焦点:使用js里面的focus方法

<input type='text'>
<script>
let search = document.querySelector('input');
document.addEventListener('keyup',function(e){
    if(e.keyCode = 83){

        search.focus()
    }
})

</script>

案例:输入框输入,显示放大数字

<body>
    <div>
        <div class = 'con'></div>
        <input type = 'text' placeholder="请输入内容" class = 'jd'>
    </div>
    <script>
        let con = document.querySelector('.con');
        let int = document.querySelector('input');
        int.addEventListener('keyup',function(e){
            if(int.value === ''){
                con.display = 'none'
            } else {
                con.display = 'block'
                con.innerText = int.value
            }
        })
    </script>
</body>

BOM部分

即浏览器对象模型;提供了独立于内容而与浏览器进行交互的对象;

BOM 把一个浏览器当做一个对象来看待;顶级对象是window;

BOM中包含DOM

 BOM的构成:window对象是浏览器的顶级对象,具有双重角色;

1、它是JS访问浏览器的一个接口;

2、它是一个全局对象,定义在全局作用域中的变量,函数都会变成window的属性和方法;

所有在调用时候可以省略window;

window对象常见的事件:

一、窗口的加载事件(方法一):

window.onload = function(){}

或者:

window.addEventListener('load',function(){})

就是当文档内容(包括,图片,样式,文本,脚本文件等)完全加载完毕后会触发这个事件。

注意:
window.onload()传统注册事件只能执行一次,如果多个只会执行最后一个window.onload

window.addEventListener('load',function(){})可以有多个;

二、窗口加载事件(方法二)

window.addEventListener('DOMContentLoaded',function(){});

仅当DOM加载完毕后就可以触发,不包括样式,图片脚本等;

定时器倒计时效果:

<script>
    let hour = document.querySelector('.hour');
    let minute = document.querySelector('.minute');
    let second = document.querySelector('.second');
    let inputTime = +new Date('2023-6-1 18:00:00');    //获取当指定时间的时间戳
    countDown();  //为了防止定时器页面刷新空白时间,先执行一次定时器
    setInterval(counTDown, 1000);     //定时器每隔几秒执行一次
    function countDown() {          //倒计时时间戳函数
        let nowTime = +new Date();
        let times = (inputTime - nowTime) / 1000;  当前剩余秒数
        let h = parseInt(times / 60 / 60 % 24);   获取剩余小时
        let m = parseInt(times / 60 % 60)
        let s = parseInt(times % 60)
        h = h < 10 ? '0' + h : h;
        m = m < 10 ? '0' + h : m;
        s = s < 10 ? '0' + s : s;
        hour.innerText = h
        minute.innerText = m
        second.innerText = s
       

    }

</script>

清除定时器:

<button class = 'beg'>开始定时器</button>
<button class = 'stop'>关闭定时器</button>
<script>
    let beg = document.querySelector('beg');
    let stp = document.querySelector('stop');
    let timers = null
    beg.addEventListener('click', function(){
    let timers = setInterval(()=>{

    console.log('123132');
    },2000)
    })
    
    stp.addEventListener('click', function(0){
      clearInterval(timer)
    })
    


</script>

this的指向问题

1、全局作用域或者普通函数的this指向全局对象window(注意:定时器里面的this指向window)

function fun(){
    console.log('this在全局作用域或者普通函数指向的是window')
}
window.fun()

2、在方法中this的指向,

let a = {

    sayHi: function(){

        console.log(this)
    }

}
a.sayHi();




-------------------------
let btn = document.querySelector('button');
btn.onclick = function(){
    console.log();

}

3、构造函数中this指向的是new的创建的实例

重点:

JS执行机制——同步和异步

同步:前一个任务结束后才可以执行后一个任务。程序的执行顺序和任务的顺序是一致的。通俗的就是,一次只能做一件事,只有这件事做完才可以做另一件事。

异步:可以执行好几个任务

<script>

    console.log('123')
    setTimeout(function(){

    console.log('456')
    })

    console.log('789')
</script>

程序执行结果是:123789456

js执行时会先执行主线程里边的同步任务,执行完后再执行任务列队(消息队列)中的异步任务。

先执行执行栈中的同步任务,

异步任务放入任务队列中;

一旦同步任务都执行完毕,开始执行异步任务。

一般异步任务有三种类型:

1、普通事件;

2、资源加载;

3、定时器;

当多个同步异步任务都有时:

 首先会先放到异步进程处理里边,事件,定时器,资源加载都会先放进这里边,对于事件,如果没有触发就不放到异步任务队列里边,定时器如果没有到事件也不会放进入。

同时,每次异步进程都会去查看任务队列里是否有任务,

 

location对象

window对象给我们提供了一个location属性用于获取或设置窗体的URL,并且可以用于解析URL。因为这个属性返回的是一个对象,所以我们将这个属性也称为Location对象。

案例:获取不同页面之间的数据传递

<body>
    <form action = 'index.html'>
        用户名:<input type = 'text' name = 'uname'>
        <input type = 'submit' value ='登录'>
      
    </form>
</body>

//从页面一向页面二跳转

<body>
    <div></div>
    <script>
        //location.search获取到的就是传过来url上的?后边的参数
        let params = location.search.substr(1);   //uname = andy
        let arr = params.split('=');    // 利用 = 把字符串分割为两个数组
        
        let divs = document.querySelector('div')
        div.innerHTML = arr[1] + '欢迎您'
    </script>
</body>

location的常见用法:

1、location.assign():与href一样,可以跳转页面(重定向页面),带历史记录,可以后退

<body>
    <button></button>
    <script>

        let btn = document.querySelector('button');
        btn.addEventListener('click', function(){
            location.assign('http://www.baidu.com')
        })

    </script>
</body>

2、location.replace():替换当前页面,因为不记录历史,所以不能后退;

<body>
    <button></button>
    <script>

        let btn = document.querySelector('button');
        btn.addEventListener('click', function(){
            location.replace('http://www.baidu.com')
        })

    </script>
</body>

3、location.reload():重新加载页面,相当于刷新按钮或者F5,如果参数为true,强制刷新;

<body>
    <button></button>
    <script>

        let btn = document.querySelector('button');
        btn.addEventListener('click', function(){
            location.reload()  
            //location.reload(true)  强制刷新
        })

    </script>
</body>

navigator对象

包含浏览器的信息,有很多属性,最常用的userAgent,这个属性可以返回客户机发送服务器的user-agent头部的值。

history对象 

offset相关介绍

offset简介:动态获取到当前该元素的位置(偏移),大小等。

1、获得元素距离带有定位父元素的位置。

2、获得元素自身大小(宽度高度)

3、注:返回的值不带单位。

常用的offset属性有:

element.offsetParent:返回当前元素带有定位父级元素,如果父级都没有定位则返回body;

(注意:它和node.parentNode有区别,前者返回带定位父元素,后者是最近一级父元素)

element.offsetTop:返回元素相对带有定位父元素上方的偏移;

element.offsetLeft:返回元素相对带有定位父元素左边框的偏移;

element.offsetWidth:返回元素自身包括padding,边框,内容区的宽度,返回数值不带单位;

element.offsetHeight:返回元素自身包括padding,边框,内容区的高度,返回数值不带单位;

<div style="position:relation" class = 'f'>
    父元素
    <div style="position:" class = 's'>子元素</div>
</div>

<script>

    let f = document.querySelector('.f');
    let s = document.querySelector('s');

    console.log(s.offsetParent)
    console.log(s.offsetTop);
    console.log(s.offsetLeft);
    console.log(s.offsetWidth);
    console.log(s.offseTHeight)
</script>

offset和style的区别:

offset可以获取到任意样式表中的样式值;

但是获取到的值没有单位;

offsetTop和offsetLeft是包含padding和边框和内容宽度,高度的;

并且offset系列不可以修改值;

-------------------------------------

style只可以获取到行内样式表的样式值,

但是获取到的值是带有单位的;

style.width不包含有padding和border值,

style.height是可读写属性,可以获取到值,也可以赋值,所以如果需要更改样式大小值,可以使用;

<body>
    <div style="width: 300px"></div>

    <script>
        let d = document.querySelector('div');
        d.style.width = '400px'
    </script>


</body>

实例:获取到鼠标移动时在盒子里的坐标(e.pageX,  e.pageY)

<body>
    <div class = 'divClass'></div>
    <script>
        let di = document.querySelector('.divClass')
        di.addEventListener('mousemove', function(e){
            console.log(e)     //打印输出的是事件对象
            let x = e.pageX - di.offsetLeft
            let y = e.pageY - di.offsetTop
            console.log('当前点击盒子里坐标x 为'+x+'y坐标为:'+ y);

        })

    </script>


</body>

实例拖拽模态框案例

由于代码稍微多,具体请看pink老师教程:
【JavaScript前端课程-dom-bom-js-es6新语法-jQuery-数据可视化echarts黑马pink老师前端入门基础视频教程(500多集)持续】 https://www.bilibili.com/video/BV1Sy4y1C7ha/?p=292&share_source=copy_web&vd_source=0b14fab0cad18656d9ffed500fb3ca30

关键代码如下:

 

<script>
    let login = document.querySelector('.login');
    let mask = document.querySelector('.beijing');
    let link = document.querySelector('#link');
    let title = document.querySelector('.tit');
    let closeBtn = document.querySelector('#btn');
    点击弹出让登录框,背景显示出来
    link.addEventListener('click', function(){
        mask.style.display = 'block'
        mask.style.display = 'block'
       
    })
    closeBtn.addEventListener('click', function(){
        mask.style.display = 'none'
        mask.style.display = 'none'
    })

    title.addEventListener('mousedown', function(e){
        //获取到当前鼠标按下后的下盒子里坐标
     let x = e.pageX - login.offsetLeft
     let y = e.pageY - login.offsetTop
//鼠标移动时,把当前鼠标在页面坐标减去在盒子里坐标赋值给Login
        document.addEventListener('mousemove', mov)
        function mov(e){
            login.style.left = e.pageX - x
            login.style.top = e.pageY - y
        }
        document.addEventListener('mouseup', function(){
            document.removeEventListener('mousemove', mov);
        })
        
    })

</script>

元素可视区client系列

client翻译过来就是客户端,使用client系列的相关属性来获取元素可视区的相关信息。通过client的相关属性可以动态得到该元素的边框大小,和元素大小等。

client系列属性(不包括边框)
element.clientTop: 返回元素上边框的大小,没有单位

element.clientLeft: 返回元素左边框的大小,没有单位

element.clientWidth: 返回自身包括padding,内容区的宽度,没有单位

element.clientHeight: 返回自身包括padding ,内容区高度的值(没有单位)

立即执行函数:不需要调用直接执行

两种写法:

1、(function(){})()

(function(a,b){

        console.log('123')

})(1,2)

括号里传参

2、(function(){}())

(function sum(a,b){

        console.log('abc');

}(2,3))

元素滚动scroll系列

动态的可以获取到元素的大小,滚动距离等。

element.scrollTop:返回被卷去的上边距离,不带单位。

element.scrollLeft: 返回被卷去的左侧距离,不带单位。

element.scrollWidth: 返回元素实际自身的宽度,不包括边框,不带单位。

element.scrollHeight: 返回元素自身的高度,不包括边框,不带单位

新方法:window.pageYOffset

window.pageXOffset   分别表示:返回窗口距离X轴方向的距离,返回Y轴方向距离

<bod>
  <div>
    <span>返回头部</span>
  </div>
    <div class = 'header w'>头部</div>
 <div class = 'banner w'>banner</div>
 <div class = 'main w'>主体部分</div>


 <script>

   let sliderbar = document.querySelector('.slider-bar')
    
   document.addEventListener('scroll', function(){
     console.log(window.pageYoffsetLeft);
     console.log(window.pageXoffsetTop);
        if(window.pageYoffset >= 172){
            sliderbar.style.position = 'fixed'
        }
        else {
            sliderbar.style.position = 'absolute'
        }
    })
</script>
</body>

三个系列总结:

1、首先:element.offsetWidth:获取自身的宽度高度,包括边框宽度,padding的宽度;

offset系列经常用于获取元素的位置offsetLeft和offsetTop;

2、element.scroll:获取的是被卷去部分的宽度,高度,不包括边框;scroll系列经常用于获取滚动距离,scrollLeft,scrollTop;

3、element.client:获取的是包括自身,也包括Padding,不包括边框的值,因为它可以获取边框宽度,经常用于获取滚动的距离scrollTop,scrollLeft

注:页面滚动的距离是通过window.pageXoffset或者window.pageYoffset获取到;

mouseenter和 mouseover的区别:

<body>

    <div class = 'f'>父盒子
        <div class = 's'>子盒子</div>
    </div>
    <script>
        let f = document.querySelector('f');
        let s = document.querySelector('s');
        s.addEventListener('mouseenter', function(){
            console.log('子盒子鼠标滑过不会触发父盒子')

        })

       // ----------------------
        s.addEventListener('mousemover',function(){

            console.log('会冒泡到父盒子,');
        })
    </script>
</body>

动画函数的简单封装:

注:这个简单函数需要传递两个参数。

<script>

    function fun(obj,num){
    let timer = setInterval(function(){
        if(obj.offsetLeft >= num){
            clearInterval(timer)

        } else{
            obj.offsetLeft = obj.offsetLeft + 1 + 'px'
        }
    },500)
    }
    let div = document.querySelector('div')
    fun(div,500)


</script>

怎样给不同元素记录不同定时器

如果多个元素都使用这个定时动画函数,每次都会创建一个定时器,会影响效率。

所以可以采用为每个对象使用不同定时器(对象使用自己的定时器)

核心原理:js是一个动态语言,可以为当前对象添加属性;

同时:为了防止每次执行函数都会创建一个定时器的问题,每次执行函数之前先清除前一个定时器;

<body>

    <div></div>
    <script>

        function animate(obj, num){
            clearInterval(obj.timer)    //为了防止创建多个相同定时器,每次执行先清除前一个定时器
            obj.timer = setInterval(function(){
                if(obj.offsetLeft >= num){
                clearInterval(tim)

                } else {
                    obj.offsetLeft = obj.offsetLeft + 10 + 'px'
                    
                }


            }, 500)

        }
        animate(div,200)


    </script>
</body>

动画函数封装——动画缓动效果

原理:就是让元素运动速度有所变化;

思路:

1、让每次移动的距离慢慢变小,速度就相应的慢下来;

2、核心算法:(目标值 - 现在位置)  / (步长数) =  每次移动的距离;

3、停止条件:让盒子位置等于目标位置就停止定时器;

<body>

    <div></div>
    <script>
           // obj是元素,num是目标值
        function animate(obj, num){
            clearInterval(obj.timer)//为了防止创建多个相同定时器,每次执行先清除前一个定时器
            obj.timer = setInterval(function(){
                let step = (target - obj.offsetLeft) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step)
                if(obj.offsetLeft >= num){
                    clearInterval(obj.timer);
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            }, 500)
        }
        animate(div,200)
    </script>
</body>

动画添加回调函数:

<head>

    <script src='animate.js'></script>
</head>
<body>
    <div class = 'sliderbar'>
        <span>箭头</span>
        <div class = 'con'>滑动滑块</div>
    </div>
    <script>
        let sliderbar = document.querySelector('.sliderbar');
        let con = document.querySelector('.con');
        sliderbar.addEventListener('mouseenter', function(){
            animate(con, -200, function(){
                sliderbar.children[0].innerHTML = '滑到右边'
            })
        })
        sliderbar.addEventListener('mouseleave', function(){
            animate(con, 0, function(){
                sliderbar.children[0].innerHTML = '滑动回来'
            })
        })
    </script>
</body>

节流阀:

防止动画执行太快,当上一个执行完毕再执行下一个;

案例:筋斗云案例

思路:

1、利用动画效果实现;

2、原始位置是0,;

3、鼠标经过某个小Li就把当前Li的OffsetLeft作为目标值;

4、鼠标离开某个小li就把目标值设为0;

5、点击那个li,就把当前li点击位置存到原始位置遍历;

<script>
    let current = 0;
    for(let i =0;i<lis.length;i++) {
       lis[i].addEventListener('mouseenter', function(){
        animate(cloud, lis[i].offsetLeft);
        })
       lis[i].addEventListener('mouseleave', function(){
            animate(cloud, current)
        })
        lis[i].addEventListener('click', function(){
            current = this.offsetLeft;
        })
    }


</script>

移动端事件:

触屏touch事件

touchstart :手指触摸到一个DOM元素时触发;

touchmove: 手指在一个DOM元素滑动时触发;

touchend; 手指从一个DOM元素上移开时触发;

let div = document.querySelector('div');
div.addEventlistener('touchstart', function(){
 console.log('移动端开始触摸事件')

})


---------------------------
div.addEventlistener('touchmove', function(){

    console.log('移动端在元素上移动事件');
})
-----------------------
div.addEventlistener('touchend', function(){
    console.log('移开元素')

})

1、触摸事件对象(TouchEvent)

有三个常见对象列表:

1.touches:正在触摸屏幕的所有手指的一个列表,有几个手指在触摸返回几个;

2.targetTouches:正在触摸当前DOM元素上的手指的一个列表;

3.changedTouches:手指状态发生了改变的列表,从无到有,从有到无的变化;

本地存储

特性:

1、数据是存储在浏览器中;

2、设置,读取方便,页面刷新也不会丢失数据;

3、容量大,但是只能存储字符串,可以将对象JSON.stringify()编码后存储;

一、window.sessionStorage

生命周期为关闭浏览器窗口;

在同一个页面,窗口下数据共享;

以键值对形式存储使用;

(1)、存储数据到本地浏览器中;

(window.)sessionStorage.setItem(key, value)

(2)、获取到本地浏览器中存储的数据;

sessionStorage.getItem(key)

(3)、删除数据;

sessionStorage.removeItem(key)

(4)、清空所有浏览器中数据

sessionStorage.clear()

二、window.localStorage

声明周期永久生效,除非手动删除;

同样也是以键值对形式存储数据;

多窗口,页面共享数据;

(1)、存储数据;

localStorage.setItem(key,value)

(2)、查询数据;

localStorage.getItem(key)

(3)、删除数据

localStorage.removeItem(key)

(4)、清空

localStorage.clear()

小实例:

<script>
    <input type = 'text' id = 'username'> <input type = 'checkbox'>勾选</input> </input>

    let username = document.querySelector('#username');
    let remember= document.querySelector('#remember');
    if(localStorage.getItem('username')) {
        username.value = localSorage.getItem('username');
        remember.checked = true
    }
    remember.addEventListener('change', function(){
        if(this.checked) {
            localStorage.setItem('username', username.value)
        } else {
            localStorage.removeItem('username')
        }

    })

</script>

------------------------

JQuery

是一个快速的JavaScript库;

JQuery的基本使用——入口函数

$(function(){

})

或者:

$(document).ready(function(){})

使用方式一:

<body>
    <script>
    $(document).ready(function(){
        $('div').hide()
    })
    
    </script>
    <div></div>

</body>

使用方式二:

<body>

    <div></div>
    <script>

        $(function(){
            $('div').hide()
        })

    </script>

</body>

1、等DOM结构渲染完毕后即可执行内部代码,不必等到所有外部资源加载完成;

2、相当于原生js中的DOMContentLoaded;

3、不同于原生js中的load事件,外部资源文件加载完才执行内部代码;

jQuery的基本使用——顶级对象“$”

“$” 是jQuery的别称,在代码中可以使用jQuery代替;

DOM对象和jQuery对象

1、使用原生js获取到的对象就是DOM对象

let divs = document.querySelector('div')

2、jQuery方法获取的元素就是jQuery对象,其本质就是$对DOM对象包装后产生的对象。

$('div'): 获取到的是jQuery对象

jQuery对象只能用jQuery的方法,

$('div').css('background', 'pink')
DOM对象使用的是原生的js属性和方法;

divs.style.display = 'none'

DOM对象和jQuery对象可以相互转换

1、DOM对象转为jQuery对象

<body>
    <video src = 'mv.mps'></video>
    <script>
        $('video'); 
        let myvideo = document.querySelector('video')
        myvideo.play();
    </script>

</body>

(1)、直接获取视频,得到的就是jQuery对象;

2、jQuery对象转为DOM对象(两种方式)

1、$('div')[index]  : index是索引号

<video></video>
<script>
    $('video')[0].play()
    //或者
    $('video').get(0).play()
</script>

2、$('div').get(index) :  index是索引号

jQuery选择器

jQuery基础选择器:$("选择器")  //里边选择器直接写css选择器即可,需要加引号

层级选择器:

(1、)子代选择器:

$('ul  > li') : 只获取到“儿子”层级元素;

(2、)后代选择器:

$('ul li')  :  获取到父级下边所有元素;

jQuery隐式迭代

<div></div>
<div></div>
<ul>
    <li></li>
    <li></li>
</ul>
<script>
//直接获取到元素,然后设置背景
    $('div').css('background', 'red')
    
//隐式迭代
    $('ul li').css('background', 'red')
</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会尽力回答您关于计算机组成原理存储系统部分的问题。 计算机存储系统是计算机中的重要组成部分,它主要用于存储数据和程序。存储器可以分为主存储器和辅助存储器两种类型。 主存储器是计算机中用来暂时存储数据和程序的地方,也叫内存。它是由一系列的存储单元组成的,每个存储单元都有一个唯一的地址。主存储器的读写速度非常快,但是存储容量较小,一般只能存储几十到几百兆的数据。 辅助存储器则是用于永久存储数据和程序的地方,也叫外存。它的存储容量非常大,可以存储几百到几千兆的数据。但是,辅助存储器的读写速度比主存储器慢得多,一般需要几毫秒的时间来完成一个读写操作。 在计算机组成原理中,有几个重要的概念需要注意: 1. 存储器层次结构:计算机的存储器层次结构分为多层,每一层的存储器容量和读写速度都不同。一般来说,离 CPU 越近的存储器读写速度越快,但容量越小。 2. 存储器地址和数据的二进制表示:计算机中的所有数据和指令都是以二进制的形式存储的,每个存储单元都有一个唯一的地址。地址和数据的二进制表示方式是计算机组成原理中需要掌握的重要概念。 3. 存储器的访问方式:存储器可以按照字节、字、块等不同的方式进行访问,不同的方式对应着不同的读写速度和操作方式。 以上是关于计算机组成原理中存储系统部分的一些基本概念和注意事项,如果您有具体的问题需要了解,可以继续提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值