个人自学前端10-JS3-DOM操作和表达式,操作符和表达式,逻辑运算符和三目运算符

DOM操作和表达式

document object model => 通过js操作页面上的元素
document => 文档 => html文档

一 DOM操作入门

DOM操作包含两部分基本操作:

1:获取标签(元素)(节点)

2:操作数标签(元素)(节点)

1.1 获取元素

html标签在DOM中用 js 标签对象来表示。(标签都是js对象)

js 标签对象有很多默认的属性,不同属性有不同作用。

获取方法:

// 通过id获取元素(只获取一个)
let oDiv = document.getElementById(元素id);
// 通过标签名获取元素(获取一堆)
let aDiv = document.getElementsByTagName(元素标签名);
// 通过类名获取元素(获取一堆)
let aDiv = document.getElementsByClassName(元素类名);
// 通过选择器获取元素(只获取一个)
let oDiv = document.querySelector(选择器);
// 通过选择器获取元素(获取一堆)
let aDiv = document.querySelectorAll(选择器);

如果标签不在页面中,则返回null。

1.2 操作元素

js 可以操作html标签的内容和属性。

js 不能操作html标签的样式,只能操作html标签的style属性。

js 获取到的任何关于html标签的数据,都是字符串!(html标签的内容,属性,样式都是字符串!)

1.2.1 操作元素内容

两个方法:

// 获取元素内容
console.log(oDiv.innerText);
console.log(oDiv.innerHTML);

// 设置元素内容
oDiv.innerText = 新的内容;
oDiv.innerHTML = 新的内容;

其中:

innerHTML可以获取html标签内容,并且可以实现插入新标签。

innerText只能获取和操作文本内容。

// 反引号支持换行
    oDiv.innerHTML = `
      <p>uuuuuu</p>
      <p>ttttttttt</p>
    `;
1.2.2 操作元素行间样式

html标签是一个 js 对象, html标签的style属性也是一个 js 对象。style对象是标签对象的一个属性。

// 获取行间width样式
console.log(oDiv.style.width)
// 设置width属性。
oDiv.style.width = '100px';

// 如果样式名带-,需要写成驼峰形式
oDiv.style.marginLeft = '100px';

js 只能获取行间样式和操作行间样式,不能获取和操作内部样式和外部样式。

js 只能获取最终样式。不能设置

// 获取优先级最高的那个width样式 (最终的width样式)
getComputedStyle(oDiv).width
1.2.3 操作元素属性

html标签的属性可以在对应的 js 对象中通过 js 对象属性获取。(html标签属性和 js 对象属性不要混为一谈)

因此,给 js 标签对象添加新属性,html标签并不会多出新的属性。

同样,删除 js 标签对象的属性,html标签并不会删除对应属性。

js 标签对象默认拥有的属性是html标签的全局属性,事件属性和可选属性。

因此通过 js 我们也可以操作html标签的全局属性,事件属性和可选属性。

// 获取对应的html标签属性。class属性需要写成className
console.log(oDiv.id);
console.log(oText.value);
console.log(oText.className);

// 设置元素的id属性
oDiv.id = 'wrap';
oText.value = '你好吗';
oText.className = 'active';

标签的布尔属性,用 js 获取,得到的就是布尔属性。例如checked,mutiple,disabled属性

// 获取复选框的checked属性,得到的值就是true或者false
console.log(oCheckbox.checked)// true或者false
// 通过设置checked属性可以控制复选框的勾选状态
oCheckbox.checked = true
// 禁用oBtn
oBtn.disabled = true

标签的自定义属性默认在对应 js 标签对象上没有,因此不能通过操作 js 标签对象来操作html标签的自定义属性。

可以通过标签对象的getAttribute方法来获取自定义属性。

可以通过标签对象的setAttribute方法来设置自定义属性。

// 获取abc自定义属性。
oDiv.getAttribute('abc');

// 把abc自定义属性设置为wwww。
oDiv.setAttribute('abc','wwww');
标签属性:
1:全局属性 所有标签都可以使用的属性。常见是id,class,style,title
2:可选属性 不同标签的可选属性不一样。例如img标签可以有width属性,div没有。
3:自定义属性,开发人员为了某种目的,自己添加的属性
4:事件属性。数据属性都以on开头。on+事件名,事件属性的属性值是js代码
1.2.4 添加事件

什么是事件?

特定情况下,发送的事情,例如下雨了,下课了。

事件发生后会有对应的事件现象。例如,下雨了,大家都会撑伞,下课了,大家都去吃饭。

标签也有对应的事件,例如,按钮被点击了。这里点击就是一个事件。

如果点击按钮,需要产生某些效果,则需要通过事件属性来添加代码实现需要的效果。

通过操作 js 标签对象的事件属性,可以给标签添加事件。事件需要实现的效果需要需要写在函数内

// 给按钮添加点击事件,事件发生产生的效果写在函数内。
// 点击按钮,弹出100
oBtn.onclick = function(){
	alert(1000)
}

// 或者
oBtn.onclick = show;
function show(){
    alert(1000)
}

常见事件(注意事件没有驼峰):

onclick。(点击事件)

onmouseover,onmouseout。(鼠标移入移出事件)

onmouseenter,onmouseleave。(鼠标移入移出事件)

onblur,onfocus (失去获得焦点事件)

onchange (value改变事件)

oninput (正在输入事件)

onmousedown,onmouseup (鼠标按下松开事件)

onkeydown,onkeyup (键盘按下松开事件)

事件产生的效果,为什么要写在函数内?

我们知道,js的运行是发生在html文档的解析阶段的,而事件需要实现的效果是发生在html文档渲染之后的,

如何让某些代码在html文档在渲染之后才执行呢?通过函数就可以。

**函数可以决定某些代码什么时候执行,这是函数的一个显著特征。

二:操作符(运算符)

程序中需要对数据进行各种运算,以得到计算后的结果。

计算有很多种类型,不同计算方式需要使用不同的操作符。

注意,这里的计算不限于传统的数学计算,实际上数学运算只是编程运算中的一小部分。

常见运算符:

1:算术运算符

2:比较运算符

3:逻辑运算符

4:三目运算符(条件运算符,三元运算符)

5:其他运算符

操作数:用于计算的数据叫运算符的操作数。

根据操作数的不同个数,还可以把运算符分为:

1:单目运算符

2:双目运算符

3:三目运算符

大多数的运算符都是双目运算符,小部分是单目运算符,三目运算符只有一个。

三:表达式

编程本质上都是在处理数据和数据逻辑。

那程序是如何表示数据的?程序中的数据都是怎么获得的?

程序中的所有数据都是通过表达式获得的。表达式是程序中最基本的组成单元。

任何的数据,程序都是通过表达式来获取或者表示的。

表达式分类:

1:原始表达式

单个常量和单个变量。

如果是object类型的常量,一般叫直接量,也可以看作原始表达式。

对象的属性访问和数组的元素访问,也可以看作原始表达式。

2:计算表达式

操作数 + 操作符构成的表达式。

操作数本身是数据,因此操作数本身也可以通过任意的表达式来提供。

// 1+1 => 这是两个常量1和运算符 + 构成的表达式。
// 第一个操作数1同时也可以通过表达式0.5+0.5来提供,写成 (0.5+0.5)+1

3:函数调用表达式

函数调用也可以提供数据,构成函数调用表达式。

// Math.random() => 这是函数调用表达式,它和其他表达式一样提供一个结果,赋值给变量res
let res = Math.random();

表达式的返回值:

表达式经过计算得到的结果就是表达式的返回值。

表达式一定有返回值。

// 1+1 计算的结果是2,因此我们说表达式 1+1的返回值是2
// 以下代码的意义为:把1+1的返回值赋值给变量x。
let x = 1+1;
// 以下代码的意义为:把Math.random()的返回值赋值给变量res
let res = Math.random();

操作符和表达式

一:算术运算符

小学就学过的是:+,-,*,/,计算顺序也是先乘除,后加减。

1.1.1:取余(取模):%

取余运算符,求两个操作数的余数。

// 4/2 => 求商,得2
// 4%2 => 求余数,因为可以整除,余数为0,因此计算得0
// 2%4 => 求余得2.
// 3%5 => 求余得3.
// 0%5 => 求余得0.
// 结论:如果较小的数取余较大的数,结果是较小的数

1.1.2:++

自增。单目运算符。分为前自增和后自增。计算后变量的值+1。只能操作变量。是一种语法糖。

let x = 10;
// 前自增
++x;
// 后自增
x++;

// 不管是前自增还是后自增,x的值经过计算后都+1

前自增和后自增在进行赋值时会有区别。

let x = 10;
// 如果是后自增。y的值是10.x的值是11
let y = x++;
// 如果是前自增,y的值是11.x的值是11
let y = ++x;

// 为什么会这样?

//let y = x++;可以用完整的赋值逻辑表示如下:
// 先把x赋值给y
let y = x;
// 再把x加1
x = x + 1;

//  y = ++x;可以用完整的赋值逻辑表示如下:
// 先把x加1
x = x + 1;
// 再把x赋值给y
let y = x;

总结:前置++,计算结果是+1之后的值。后置++,计算结果是+1之前的值。

难点:区分x++,++x和x的区别。

二:比较运算符

初中就学过的:>,<,>=,<=

布尔值:一种JavaScript的数据类型,表示真假,对错,有无。

比较运算符计算得到的结果都是布尔值。

1.2.1 值等 ==

判断两个数是否相等,用的是 == ,注意 = 是赋值,不是判断相等。

如果两个操作数都是object类型。则比较的是两个对象是否是同一个对象。

// 比较两个数字的值是否相等
let x = 10;
let y = 20;
console.log(x == y);//false

// 比较两个对象是否是同一个对象。
let obj1 = {};
let obj2 = {};
console.log(obj1 == obj2);//false

1.2.2 全等 ===

判断两个数的值和类型是否全等。值和数据类型必须都一致才会返回true

let x = 1;
let str = '1';
console.log(x == str);// true
// x的数据类型是number,str的数据类型是string,类型不一样。因此是false。
console.log(x === str);// false

1.2.3 值不等 !=

判断两个数据的值是否相等。

let x = 10;
let y = 20;
console.log(x != y);//true

1.2.4 值不等或者类型不等 !==

判断两个数据的值不等或者类型不等,只要有一个不等,都返回true,如果全部相等返回false

let x = 2;
let str = '2';
// 值等,因此是false
console.log(x != str);// false
// 值等,但是类型不等
console.log(x !== str);// true

let x = 2;
let y = 2;
// 值和类型都相等。
console.log(x !== y);// false

三:判断

判断不是表达式,是控制结构中的一种。让我们可以实现类似如果....否则....这样的程序逻辑。

语法:

if(条件){
	条件为真需要做的事
}else{
	条件为假需要做的事
}

其中条件可以由任何表达式提供。

当这个表达式的返回值是true时执行第一个代码块。

当返回值是false时,执行第二个代码块。

几种拓展的表现形式:

1:只有如果,没有否则

if(条件){
	条件为真做的事情
}

// 这种写法可以省略{},但是极度不推荐

2:有很多的条件判断

if(条件1){
	条件1为真做的事情
}else if(条件2){
	条件2为真做的事情
}
.........
else{
	所有条件都为假时做的事情。
}

// 这种写法,如果多个条件同时为真,则只执行第一个真条件匹配的代码段,其他的代码段不执行

3:switch判断

switch判断有时候可以简化多个 if.else if的判断书写。

// 类似以下的判断形势可以用switch代替
if(变量 == 值1){
	相等时做的事情
}else if(变量 == 值2){
	相等时做的事情
}
.........
else{
	所有值都不等时做的事情。
}

// 以下写法,break不能省略,它可以防止多个值都为真时错误的执行多个语句
// default 的作用类似于最后一个else。
switch(变量){
	case 值1:
		变量等于值1时做的事情;
		break;
	case 值2:
		变量等于值2时做的事情;
		break;
	........
	default:
		所有值都不等时做的事情。
}

四:隐式转换

1.1 转换现象

很多时候,操作数的数据类型是有规定的。

比如,算术运算符的操作数的数据类型必须是数字,因为不是数字无法计算。

但是,js在书写上却允许不是数字的数据进行算术运算。

因为js是弱类型的编程语言,对数据类型不敏感,在需要的时候会自动进行类型转换。


console.log('1' * 2 );//结果是2
// '1' * 2 => 第一个操作数是字符串 '1',不是数字,因此理论上不会进行相乘计算。
// 为了让以上运算正常执行,js自动把字符串 '1'转换成了数字1.实际进行的计算是 1*2

另外,比较运算符的操作数也应该是数字,如果不是,js会自动转换为数字在进行比较运算。


console.log('1' < 2);// 结果是true
// 理论上字符串 '1' 是不能和数字2进行比较大小的,为了让运算完成,js会自动把'1'转换成数字1以后再比较。

判断语句的判断条件的值应该是布尔值,如果不是,js会自动转换条件的值为布尔值,然后再判断

// 100是数字,不是布尔值,为了让判断执行,js会把100转换为布尔值true,然后再进行判断
if(100){
	console.log('100是true')
}

100转换为布尔值为什么是true,为什么不是false?什么东西转换为布尔值是false?

重点: js的世界中,只有5种常量转换为布尔值是false,其余都是true;

这5个值是:NaN,0,'' (空字符串),undefined,null。

在js的世界中,隐式转换无处不在。再比如,alert(),括号内的值应该是字符串,如果不是,js会自动转换为字符串.


// window是对象,不是字符串,因此js自动把window转换成了字符串[Object object]
alert(window);// [Object object]

// 文本框获取的value是字符串,*1之后会变成数字100
    let num = oText.value * 1 + 50;

1.2 显示转换

对应的数据类型的转换方法:

1:把任意值转换为number类型 Number (待转换的值)

2:把任意值转换为string类型 String (待转换的值)(还有很多)

3:把任意值转换为boolean类型 Boolean (待转换的值)

不存在把其他值转换为对象的方法。因为万物皆对象。

1.3 转换规律

1:算术运算符

默认会把不是数字的操作数隐式转换为number类型。

例外:

如果是 + 操作符,如果有一个操作数是字符串,则把另一个操作数隐式转换为字符串,

然后进行字符串拼接操作。

'1' + 1 => 结果是'11',而不是2

2:比较运算符

默认会把不是数字的操作数隐式转换为number类型。

例外:

如果是 == 操作符,如果比较的两个操作都是对象,则比较两个对象是不是同一个对象,而不会进行隐式转换。

3:判断条件

默认会把判断()内的值转换为布尔值。没有例外。

会转换为布尔值的5个常量:NaN,0,空字符串,undefined,null

1.4 编程经验

利用隐式转换转换字符串为数字。


'2'+3 因为js默认会把3转换为 '3',因此结果是'23',如果我们希望结果是5,则需要把 '2'转换为数字,再+3
可以这样做:'2'*1+3
这样先计算'2'*1,这样js会把'2'转换为2,乘1得2,再+3得5

利用隐式转换转换其他值为字符串。


true + 2 因为js默认会把true转换为数字1,因此结果是3,如果我们希望结果是true2,则需要把true转换为字符串
可以这样做:true+''+2
这样先计算true+'',js会把true隐式转换为'true',再+2,得'true2'

逻辑运算符和三目运算符

一:逻辑操作符

逻辑运算符用于实现:并且,或者和取反操作。

1.1:! 逻辑非

逻辑非操作符是单目运算符。!操作数

计算逻辑:操作数隐式转换为布尔值是true,返回false,否则返回true。

if(!条件){
	条件为假做的事情
}

// 利用两个逻辑非可以是隐式转换任何值为布尔值
let x = !!y;

1.2:&& 逻辑与

逻辑与操作符是双目运算符。操作数1 && 操作数2

计算逻辑:第一个操作数隐式转换为布尔值是true,返回第二个操作数,否则返回第一个操作数。

用法:

//用于判断
if(条件1 && 条件2){
	条件1和条件2成立需要做的事情
}

// 用于赋值
let x = y && z;
// 此用法相当于:
let x;
if(y){
   x = z;
}else{
   x = y;
}

// 用于代替简单的if判断
条件 && 条件为真做的事情
// 类似于:
if(条件){
    条件为真做的事情
}

1.3:|| 逻辑或

逻辑或操作符是双目运算符。操作数1 || 操作数2

计算逻辑:第一个操作数隐式转换为布尔值是true,返回第一个操作数,否则返回第二个操作数。

用法:

// 用于判断
if(条件1 || 条件2){
	条件1或者条件2成立需要做的事情
}

// 用于赋值
let x = y || z;
// 此用法相当于:
let x;
if(y){
   x = y;
}else{
   x = z;
}

// 用于代替简单if判断
!条件 || 条件为假做的事情
// 相当于:
if(!条件){
   条件为假做的事情
}

二 条件运算符

唯一的一个三目运算符。也叫三元运算符。

语法:操作数1 ?操作数2 :操作数3

计算逻辑:第一个操作数隐式转换为布尔值是true,返回第二个操作数,否则返回第三个操作数。

用法:

// 用于赋值
let x = 条件 ? y : z;
// 类似于:
let x;
if(条件){
	x = y
}else{
	x = z
}

// 用于代替简单的if else
条件? 条件为真做的事情 :条件为假做的事情
if(条件){
    条件为真做的事情
}else{
    条件为假做的事情
}

// 用于代替if else if else语句(嵌套三目)
条件1 ?
	条件1为真做的事情 :
		条件2 ? 条件2为真做的事情 :条件2为假做的事情
// 类似于:
if(条件1){
    条件1为真做的事情
}else if(条件2){
    条件2为真做的事情     
}else{
    条件都不成立做的事情
}

三 运算符优先级

表达式都有返回值,因此计算表达式的操作数可以由任意的表达式来提供。

作为操作数的表达式的返回值就是实际进行运算的操作数。

因此计算表达式可以写得很复杂

// 这是用常量作为操作数
2 + 3

// 这是用变量做操作数
x + y

// 2*3的返回值与4进行算术加运算,这里运算符 + 的操作数是 6和4,相当于6*4
2*3 + 4;

// x*y的返回值与z*4的返回值进行算术加运算。
x*y + z*4

// 2*3的返回值与typeof 100的返回值进行比较运算。
2*3 < typeof 100

// 1*2的返回值与5-3的返回值进行逻辑与计算
1*2 && 5-3

//1<2的返回值和4+3的返回值和2<3的返回值进行三目运算
1<2 ? 4+3 : 2<3

// (2*3 + 4)的返回值和(1*2 && 5-3)的返回值和(x*y + delete oYm.name)的返回值进行三目运算
(2*3 + 4) ? (1*2 && 5-3) : (x*y + delete oYm.name)

当表达式内有很多操作数时,需要考虑操作符的优先级。

按操作数数目划分优先级

单目 > 双目 > 三目

按种类细分:

()> 自增自减 > 逻辑非 > 算术 > 比较 > 逻辑与逻辑或 > 三目 > 赋值 > ,

四 例题

// 01
typeof l == 'string'
        ? typeof m == 'number'
          ? m = n && l
          : m += n || l
        : l *= 2
// 01解
        if (typeof l == 'string') {
          if (typeof m == 'number') {
            if (n) {
              m = l;
            } else {
              m = n;
            }
          } else {
            if (n) {
              m += n;
            } else {
              m += l
            }
          }
        } else {
          l *= 2
        }
// 02
res = (
          typeof m == 'function'
          ? alert('m是函数')
          : typeof m == 'number'
            ? m = 0
            : m = 'default string'
        )`
// 02解
        if ( typeof m == 'function' ) {
          res = alert('m是函数')
        } else {
          if (typeof m == 'number') {
            // 把m=0的返回值赋值给res
            res = m = 0
          } else {
            res = m = 'default string'
          }
        }

杂七杂八

一. 逻辑运算符代替if

1. || => 或者 => 第一个是真,返回第一个操作数,否则返回第二个
2. && => 与 => 第一个是真,返回第二个操作数,否则返回第一个
3. ! => 永远返回布尔值.取反
4. 数1?数2:数3 => 第一是true,返回第二个,否则返回第三个
5. && => 改写单个if
posted @ 2021-07-08 15:32  暗鸦08  阅读(334)  评论(0)    收藏  举报