整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

一次弄懂JavaScript各种运算符,满满干货,速

一次弄懂JavaScript各种运算符,满满干货,速来围观!

文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注!

作者|慕课网精英讲师 然冬

算术运算符以数值(字面量或变量)作为其操作数,并返回一个单个数值。标准算术运算符是加法(+),减法( - ),乘法(*)和除法(/)。—— MDN

算数运算符是用来做算数运算的,如 + 这个符号,就是用来做加法操作。

1. N元运算

N 代表一个数,如一元运算,二元运算。

N元运算 表示由N个值产生一个新的值的规则。

* 就是一个二元运算符,他由两个数相乘产生第三个数。

JavaScript 中有三元运算符、二元运算符、一元运算符。

注意:网络上可以搜索到 JavaScript 中有更多元的运算,基本上都是使用三目(元)表达式嵌套来完成的,严格上说这不属于更多元的运算。

与算数相关的只有二元与一元运算符:

二元运算符:

  • + 加法
  • - 减法
  • * 乘法
  • / 除法
  • % 求余
  • ** 幂 (ES2016 提案)

一元运算符:

  • + 一元正号
  • - 一元负号
  • ++ 递增
  • -- 递减

2. 二元运算符

2.1 加法(+)

加法用来做求和,将 + 左右两边的数值相加,也可以用来连接字符串。

var num1=2;
var num2=3;

var total=num1 + num2;
console.log(total); // 输出:5

var firstName='hello';
var lastName='world';

var name=firstName + ' ' + lastName;
console.log(name); // 输出:"hello world"
代码块1234567891011

数字的加法就是和自然数学里的加法一样,做累加操作。

+ 碰到字符串就会把两边字符连接到一起,形成一个新的字符串。

2.2 减法(-)

减法操作是将 - 左边的数减去 - 右边的数,结果就是差值。

var totalApple=10; // 一共有10个苹果
var take=4; // 小明拿走了四个苹果

var left=totalApple - take; // 还有 10 - 4 个苹果

console.log(left); // 输出:6
代码块123456

2.3 乘法(*)

乘法操作将 * 左右两边的数相乘,结果就是积。

var result=5 * 6;

console.log(result); // 输出:30
代码块123

2.4 除法(/)

除法操作将 / 左边的数作为被除数,右边的数作为除数,最后求出结果。

var result=6 / 2;

console.log(result); // 输出:3
代码块123

在许多强类型的语言中,整数相除即便无法除尽,结果必然是整数,但在 JavaScript 中,整数相除如果无法除尽,也会返回小数部分。

console.log(2 / 5); // 输出:0.4
代码块1

上面这个结果在 Java 中会返回 0,但是在 JavaScript 中会反回 0.4。

注意:如果拿正负 0 作为除数,则结果会返回 Infinity 与 -Infinity。

2.5 求余(%)

求余事实上就是取模运算,也就是取余数。如 8 对 3 取模,结果为 2,按小学数学中的说法就是 8 除 3 得 2余2,余2就是结果。

var result=8 % 3;

console.log(result); // 输出:2
代码块123

2.6 幂(**)

幂是 ES2016 提供的新运算符,用来做乘方运算。

** 左边是底数,右边是指数,如 2 ** 3 按数学中的表示就是 23,即求 2 的 3 次方。

var total=2 ** 3; // 2 的 3次方,结果为 2 * 2 * 2 ,即8

console.log(total); // 输出:8
代码块123

在 JavaScript 中的幂运算与其他语言有些许区别,规范中指出禁止使用带有歧义的幂运算表达式。

如底数前不能跟随一元运算符。

console.log(-8 ** 2); // 在JavaScript会报错
代码块1

以上幂运算是会报错的,因为 JavaScript 无法知道是要在计算完 8 的 2 次方后求反,还是计算 -8 的 2 次方。

使用括号可以提供具体的意义,消除歧义:

console.log((-8) ** 2); // -8的2次方

console.log(-(8 ** 2)); // 计算完8的2次方后求反
代码块123

3. 一元运算符

3.1 一元正号

一元正号通常不参与数学运算,而是用作类型转换,一元正号可以很方便的将其他类型转换成数字。

var num1=+3;
var num2=+'3';
var num3=+true;
var num4=+false;
var num5=+null;
var timestamp=+new Date(); // 直接得到时间戳
代码块123456

3.2 一元负号

一元负号也可以将其他类型的数据转换成数字,但是转换完后会在前面加上负号。

var num1=-3;
var num2=-'3';
var num3=-true;
var num4=-false;
var num5=-null;
var timestamp=-new Date();
代码块123456

通常比较多的使用场景是对数字取反,让数值在正负值切换。

3.3 递增

递增操作会让数值本身增加 1。

var num=0;

num++;

console.log(num); // 输出:1

num++;

console.log(num); // 输出:2
代码块123456789

这样看,递增操作有点像x=x + 1这种操作,其实只有在后置使用时的效果是和x=x + 1一样的,也就是++x

前置使用的时候,会先做递增操作,再返回数值。

后置使用时候,会先返回数值,再做递增操作。

var num=0;

var total=1 + (num++);

console.log(total, num); // 输出:1 1
代码块12345

这个是前置使用的情况,可以看到 num 的值是 1,total 的值也是 1,也就是说 total 再累加的时候为(1 + 0),这个时候 num 的值为 0,再这个值返回后对 num 进行了递增,所以输出 num 结果为 1。

var num=0;

var total=1 + (++num);

console.log(total, num); // 输出:2 1
代码块12345

这个是后置使用的情况,total 输出结果为 2,在求和的时候就是(1 + 2),num 是在递增后再被使用的。

3.4 递减

递增操作会让数值本身减去 1。

与递增一样,递减也具有前置使用与后置使用的情况。

var num=1;
var total=1 + (num--);

console.log(total); // 输出:2

var num2=1;
var total2=1 + (--num);

console.log(total2); // 输出:0
代码块123456789

4. 优先级

算术符的优先级与自然数学中的相似,按照先乘除后加减的规则来,具体的可以参考下表:

优先级

运算类型

符号

6

括号

( … )

5

后置递增

… ++

后置递减

… --

4

一元加法

+ …

一元减法

- …

前置递增

++ …

前置递减

-- …

3

… ** …

2

乘法

… * …

除法

… * …

取模

… % …

1

加法

… + …

减法

… - …

括号 > 后置递增/后置递减 > 一元加法/一元减法/前置递增/前置递减 > > 乘法/除法/取模 > 加法/减法

可以见到,括号的优先级是最高的,所以建议在自己不确定优先级的时候,尽量使用括号决定优先级。

如:

var res=1 + 2 / 3 * 4 % 5 ** 7;
代码块1

上面这个表达式的运算顺序,即便是知道优先级,也不是一眼就能看出来的,所以建议即便是知道优先级,也使用括号将计算顺序做区分。

将想要的计算顺序用括号包裹后:

var res=1 + (((2 / 3) * 4) % (5 ** 7));
代码块1

4. 小结

算数运算符主要参与运算,N 元运算就是用 N 个值产生一个新的值,运算符有自己的特性和优先级,当表达式较长的时候,建议使用括号包裹来控制执行顺序。

欢迎关注「慕课网」,发现更多IT圈优质内容,分享干货知识,帮助你成为更好的程序员!

一阵做需求时,有个小功能实现起来废了点脑细胞,觉得可以记录一下。

产品的具体诉求是:用户点击按钮进入详情页面,详情页内的卡片标题内容过长时,标题的前后两端正常展示,中间用省略号...表示,并且鼠标悬浮后,展示全部内容。

关于鼠标悬浮展示全部内容的代码就不放在这里了,本文主要写关于实现中间省略号...的代码。

实现思路

  1. 获取标题盒子的真实宽度, 我这里用的是clientWidth;
  2. 获取文本内容所占的实际宽度;
  3. 根据文字的大小计算出每个文字所占的宽度;
  4. 判断文本内容的实际宽度是否超出了标题盒子的宽度;
  5. 通过文字所占的宽度累加之和与标题盒子的宽度做对比,计算出要截取位置的索引;
  6. 同理,文本尾部的内容需要翻转一下,然后计算索引,截取完之后再翻转回来;

代码

html代码

<div class="title" id="test">近日,银行纷纷下调大额存单利率,但银行定期存款仍被疯抢。银行理财经理表示:有意向购买定期存款要尽快,不确定利率是否会再降。</div>


css代码: 设置文本不换行,同时设置overflow:hidden让文本溢出盒子隐藏

.title {
    width: 640px;
    height: 40px;
    line-height: 40px;
    font-size: 14px;
    color: #00b388;
    border: 1px solid #ddd;
    overflow: hidden;
    /* text-overflow: ellipsis; */
    white-space: nowrap;
    /* box-sizing: border-box; */
    padding: 0 10px;
}


javascript代码:

获取标题盒子的宽度时要注意,如果在css样式代码中设置了padding, 就需要获取标题盒子的左右padding值。 通过getComputedStyle属性获取到所有的css样式属性对应的值, 由于获取的padding值都是带具体像素单位的,比如: px,可以用parseInt特殊处理一下。

获取盒子的宽度的代码,我当时开发时是用canvas计算的,但计算的效果不太理想,后来逛社区,发现了嘉琪coder大佬分享的文章,我这里就直接把代码搬过来用吧, 想了解的掘友可以直接滑到文章末尾查看。

判断文本内容是否超出标题盒子

 // 标题盒子dom
const dom=document.getElementById('test');

// 获取dom元素的padding值
function getPadding(el) {
    const domCss=window.getComputedStyle(el, null);
    const pl=Number.parseInt(domCss.paddingLeft, 10) || 0;
    const pr=Number.parseInt(domCss.paddingRight, 10) || 0;
    console.log('padding-left:', pl, 'padding-right:', pr);
    return {
        left: pl,
        right: pr
    }
}
// 检测dom元素的宽度,
function checkLength(dom) {
     // 创建一个 Range 对象
    const range=document.createRange();
    
    // 设置选中文本的起始和结束位置
    range.setStart(dom, 0),
    range.setEnd(dom, dom.childNodes.length);
    
    // 获取元素在文档中的位置和大小信息,这里直接获取的元素的宽度
    let rangeWidth=range.getBoundingClientRect().width;
    
    // 获取的宽度一般都会有多位小数点,判断如果小于0.001的就直接舍掉
    const offsetWidth=rangeWidth - Math.floor(rangeWidth);
    if (offsetWidth < 0.001) {
        rangeWidth=Math.floor(rangeWidth);
    }
    
    // 获取元素padding值
    const { left, right }=getPadding(dom);
    const paddingWidth=left + right;
    
    // status:文本内容是否超出标题盒子;
    // width: 标题盒子真实能够容纳文本内容的宽度
    return {
        status: paddingWidth + rangeWidth > dom.clientWidth,
        width: dom.clientWidth - paddingWidth
    };
}


通过charCodeAt返回指定位置的字符的Unicode编码, 返回的值对应ASCII码表对应的值,0-127包含了常用的英文、数字、符号等,这些都是占一个字节长度的字符,而大于127的为占两个字节长度的字符。

截取和计算文本长度

js// 计算文本长度,当长度之和大于等于dom元素的宽度后,返回当前文字所在的索引,截取时会用到。
function calcTextLength(text, width) {
    let realLength=0;
    let index=0;
    for (let i=0; i < text.length; i++) {
        charCode=text.charCodeAt(i);
        if (charCode >=0 && charCode <=128) {
            realLength +=1;
        } else {
            realLength +=2 * 14; // 14是字体大小
        }
        // 判断长度,为true时终止循环,记录索引并返回
        if (realLength >=width) {
            index=i;
            break;
        }
    }
    return index;
}

// 设置文本内容
function setTextContent(text) {
    const { status, width }=checkLength(dom);
    let str='';
    if (status) {
        // 翻转文本
        let reverseStr=text.split('').reverse().join('');
        
        // 计算左右两边文本要截取的字符索引
        const leftTextIndex=calcTextLength(text, width);
        const rightTextIndex=calcTextLength(reverseStr, width);
        
        // 将右侧字符先截取,后翻转
        reverseStr=reverseStr.substring(0, rightTextIndex);
        reverseStr=reverseStr.split('').reverse().join('');
        
        // 字符拼接
        str=`${text.substring(0, leftTextIndex)}...${reverseStr}`;
    } else {
        str=text;
    }
    dom.innerHTML=str;
}


最终实现的效果如下:

上面就是此功能的所有代码了,如果想要在本地试验的话,可以在本地新建一个html文件,复制上面代码就可以了。

下面记录下从社区内学到的相关知识:

  1. js判断文字被溢出隐藏的几种方法;
  2. JS获取字符串长度的几种常用方法,汉字算两个字节;

1、 js判断文字被溢出隐藏的几种方法

1. Element-plus这个UI框架中的表格组件实现的方案。

通过document.createRange和document.getBoundingClientRect()这两个方法实现的。也就是我上面代码中实现的checkLength方法。

2. 创建一个隐藏的div模拟实际宽度

通过创建一个不会在页面显示出来的dom元素,然后把文本内容设置进去,真实的文本长度与标题盒子比较宽度,判断是否被溢出隐藏了。

function getDomDivWidth(dom) {
    const elementWidth=dom.clientWidth;
    const tempElement=document.createElement('div');
    const style=window.getComputedStyle(dom, null)
    const { left, right }=getPadding(dom); // 这里我写的有点重复了,可以优化
    tempElement.style.cssText=`
        position: absolute;
        top: -9999px;
        left: -9999px;
        white-space: nowrap;
        padding-left:${style.paddingLeft};
        padding-right:${style.paddingRight};
        font-size: ${style.fontSize};
        font-family: ${style.fontFamily};
        font-weight: ${style.fontWeight};
        letter-spacing: ${style.letterSpacing};
    `;
    tempElement.textContent=dom.textContent;
    document.body.appendChild(tempElement);
    const obj={
        status: tempElement.clientWidth + right + left > elementWidth,
        width: elementWidth - left - right
    }
    document.body.removeChild(tempElement);
    return obj;
}


3. 创建一个block元素来包裹inline元素

这种方法是在UI框架acro design vue中实现的。外层套一个块级(block)元素,内部是一个行内(inline)元素。给外层元素设置溢出隐藏的样式属性,不对内层元素做处理,这样内层元素的宽度是不变的。因此,通过获取内层元素的宽度和外层元素的宽度作比较,就可以判断出文本是否被溢出隐藏了。

// html代码
<div class="title" id="test">
    <span class="content">近日,银行纷纷下调大额存单利率,但银行定期存款仍被疯抢。银行理财经理表示:有意向购买定期存款要尽快,不确定利率是否会再降。</span>
</div>

// 创建一个block元素来包裹inline元素
const content=document.querySelector('.content');
function getBlockDomWidth(dom) {
    const { left, right }=getPadding(dom);
    console.log(dom.clientWidth, content.clientWidth)
    const obj={ 
        status: dom.clientWidth < content.clientWidth + left + right,
        width: dom.clientWidth - left - right
    }
    return obj;
}


4. 使用canvas中的measureText方法和TextMetrics对象来获取元素的宽度

通过Canvas 2D渲染上下文(context)可以调用measureText方法,此方法会返回TextMetrics对象,该对象的width属性值就是字符占据的宽度,由此也能获取到文本的真实宽度,此方法有弊端,比如说兼容性,精确度等等。

// 获取文本长度
function getTextWidth(text, font=14) {
    const canvas=document.createElement("canvas");
    const context=canvas.getContext("2d")
    context.font=font
    const metrics=context.measureText(text);
    return metrics.width
}


2、JS获取字符串长度的几种常用方法

1. 通过charCodeAt判断字符编码

通过charCodeAt获取指定位置字符的Unicode编码,返回的值对应ASCII码表对应的值,0-127包含了常用的英文、数字、符号等,这些都是占一个字节长度的字符,而大于127的为占两个字节长度的字符。

function calcTextLength(text) {
    let realLength=0;
    for (let i=0; i < text.length; i++) {
        charCode=text.charCodeAt(i);
        if (charCode >=0 && charCode <=128) {
            realLength +=1;
        } else {
            realLength +=2;
        }
    }
    return realLength;
}


2. 采取将双字节字符替换成"aa"的做法,取长度

function getTextWidth(text) {
    return text.replace(/[^\x00-\xff]/g,"aa").length;
};



作者:娜个小部呀
链接:https://juejin.cn/post/7329967013923962895

天学习下css3的基础选择器类型,只有使用选择器选中了元素,才可把样式应用于元素上,所以选择器对我们来说是至关重要的。选择器允许开发者根据元素的类型、类名、ID等属性来选择性地应用样式。

下面是一个包含HTML和CSS代码的例子,展示了CSS3中的几种基础选择器如何工作

<!DOCTYPE html>  
<html lang="en">  
<head>  
<meta charset="UTF-8">  
<meta name="viewport" content="width=device-width, initial-scale=1.0">  
<title>CSS3 基础选择器示例</title>  
<style>  
    /* 元素选择器 */  
    p {  
        color: blue;  
    }  
  
    /* 类选择器 */  
    .highlight {  
        background-color: yellow;  
    }  
  
    /* ID选择器 */  
    #unique-id {  
        color: red;  
    }  
  
    /* 后代选择器 */  
    div p {  
        font-style: italic;  
    }  
  
    /* 子选择器 */  
    ul > li {  
        list-style-type: none;  
    }  
  
    /* 相邻兄弟选择器 */  
    h1 + p {  
        font-size: 18px;  
    }  
  
    /* 通用兄弟选择器 */  
    h1 ~ p {  
        margin-top: 20px;  
    }  
</style>  
</head>  
<body>  
  
<p>这是一个普通的段落,应用了元素选择器。</p>  
  
<p class="highlight">这是一个高亮显示的段落,应用了类选择器。</p>  
  
<div id="unique-id">这是一个ID为unique-id的div,它的文本应用了ID选择器。</div>  
  
<div>  
    <p>这个段落位于div内部,应用了后代选择器。</p>  
</div>  
  
<ul>  
    <li>列表项1,应用了子选择器。</li>  
    <li>列表项2,也应用了子选择器。</li>  
</ul>  
  
<h1>标题</h1>  
<p>这个段落紧接在h1之后,应用了相邻兄弟选择器。</p>  
<p>这个段落也在h1之后,但由于不是紧接的,所以只应用了通用兄弟选择器的样式。</p>  
  
</body>  
</html>

在这个例子中,我们有一个HTML文档,其中包含了各种元素,并且针对这些元素使用了CSS3中的基础选择器来应用样式。

  • 元素选择器:所有的<p>元素都会应用蓝色文本颜色。
  • 类选择器:具有class="highlight"的<p>元素会有黄色背景。
  • ID选择器:ID为unique-id的<div>元素内的文本会变成红色。
  • 后代选择器:位于<div>内部的<p>元素会以斜体显示。
  • 子选择器:<ul>元素的直接子<li>元素将不会有列表样式(即无圆点或数字)。
  • 相邻兄弟选择器:紧接在<h1>之后的<p>元素会有18px的字体大小。
  • 通用兄弟选择器:所有在<h1>之后的<p>元素都会有20px的顶部外边距,但由于相邻兄弟选择器更具体,紧接在<h1>之后的<p>还会受到它的影响(这里两个选择器都作用于相同的元素,但样式会累加或根据CSS的层叠规则来应用)。不过,在这个特定的例子中,字体大小只由相邻兄弟选择器设置,顶部外边距则由通用兄弟选择器设置。