js基础
js的使用
行内式,仅做了解
a标签,自带一定的点击跳转的功能,所以直接书写相关的js代码即可
和 非a标签,默认是没有任何自带功能的,所以想要执行一定的功能,需要通过js代码告诉浏览器应该要进行什么行为
<a href="javascript:alert('你好');">超链接</a>
内部式
在html文件中创建一个标签
这里的type可以书写可以不写 在script标签中书写相关的js代码
<script type="text/javascript">
alert('222')
</script>
外部式
新建一个js文件,扩展名.js 然后再js文件中书写相关的js代码
最后通过标签进行关联
<script src="demo.js"></script>
注意点
1.在外部式中书写内部式的代码的话,是不会执行的
2.在head中是不能获取和调用,可以在head中可以预先定义部分方法,在下面调用
原因:网页是从上向下执行,上面定义的下面可以使用
3.在html标签外部使用---效率低
浏览器有自动修复功能,修复到body的最尾部
具体过程:当标签全部创建完成就会产生一个DOM树,当外部有script标签会再次打开dom树将script放到里面----不推荐
CSS\DOM\DOM渲染树
DOM树,当标签全部创建完成就会产生一个DOM树
CSS树,当CSS创建完成后形成一个CSS树
css树在DOM树完成之后才会进行
DOM渲染树,DOM树和CSS树都生成完毕,然后使用CSS渲染DOM,形成一个新的树形结构
时序
=时间序列
代码从上到下的执行,这个过程就叫序列
序列是同步进行 时间是异步进行(暂时不让他执行,过一段时间再执行,时间也得有顺序)
特点
特点
1、加载js是需要时间,默认是同步等待
2、加载完js,会执行js的内容
3、js正常会在遇到错误时,不继续执行后面的内容,加载的js出错将不会执行这个js后续的内容,
但是不影响其他html中的js执行
4、加载的js,扩展名并不重要,加载的过程中实际上当成一个文本加载进来,然后浏览器执行时 a.js 和 a.text区别不大
会将这个文本转换为js程序按顺序解释执行
async 异步加载,加载完成后执行(你加载你的,我忙我的),不会等待
defer 当DOM渲染完成后执行,不会等待
和body里面的script的执行顺序
body>defer > async
void(0) 不产生任何历史记录,不执行任何内容,只是拥有超链接的效果
<a href="javascript:void(0)">超链接</a>
常用属性方法
1.document.body--- body标签
2.document.title--- title标签
3.document.head--- head标签
4.document.styleSheets --- css样式列表 link引入的css和style标签描述的css。每个style标签或者link标签的数据是这个列表的元素
5.document.write --- 可以向页面中写入文本或者标签(在第一次回流前调用不会覆盖当前html的内容,在第一次回流后,调用会造成当前页面中的所有内容被覆盖)
6. innerHTML所有DOM标签都有的属性,会覆盖之前的结构
7. getElementsByClassName --- 根据标签名获取到所有指定类名的列表 HTMLCollection HTML标签列表
document.getElementsByTagName---根据标签名获取到所有该标签的列表
8. alert("你好")
9. console.dir(document.getElementById("div1")) ---部分对象类型可以通过这个方法看到属性 DOM对象,正则表达式,日期对象
10. setInterval --- 每间隔1000毫米,执行这个函数一次
每次执行时会返回一个id,当取消这个不断执行的函数时,需要使用这个id,执行多次,直到清除
var ids = setInterval(()=>{
clearInterval(ids)
console.log(11111);
},1111)
11. setTimeout --- 在一定时间后执行一次这个函数
var ids=setTimeout(function(){
console.log(1);
clearTimeout(ids);//也必须清除,否则会造成内存泄漏
},1000);
注意点!!! (setTimeout中有没有第二个参数决定了 执行的时机,,
1.写时间了,就会在改该时间后执行
2.若是没写 则在任务空闲时就会执行
两种方式的先后不一定)
绑定事件的两种方式
使用标签的onclick属性
1. <div id="div1" onclick="clickHandler()">1</div>
这里是一个标签,是一个字符串,在生成DOM树之后行成DOM对象,这时才把这个 文本(就是div整个标签) 变成了 一个对象,这个对象里面有一个onclick属性,这个属性里面有一个字符串(clickHandler) 暂时不执行不编译,因为此时还没有clickHandler方法.
当系统触发这个div时,发现标签中有onclick属性,才会编译里面的内容,这时才编译运行
2. <script>
直接获取到DOM 对象,给他添加了一个onclick属性,点击他时他就会执行对象的这个方法
var i=1;
var div=document.getElementById("div1");
//点击事件
div.onclick=function(){ 对象的onclick属性
i++;
div.innerHTML=i;
}
div.onclick=clickHandler;
//函数形式(点击事件)
function clickHandler(){
i++;
div.innerHTML=i;
}
</script>
这里是获取到div1这个节点,通过div1身上的onclick属性来触发事件
变量
1.变量就是在内存中开辟一个空间,这个空间中存储的内容就是这个变量的值,这个空间的名字叫做变量名
2.变量存储空间中的值是可以被修改的,在js中变量存储空间中的值修改时可以不用考虑其他类型的变量
3.js是弱类型语言
4.常量(const) 空间中存储的值第一次定义后就不允许修改
js 是一种点语法语言 认为一切核心都是对象,对象的属性可以使用.隔开
例子:张三 {手:2 ,眼睛:2,鼻子:1} 张三.手
js认为一切的根元素是window,所以早期所有变量都会被存储在window中,作为window的属性存储
三种声明方式:
-
a=1 其实等于window.a
-
var b=1;
var 做了定义的预解析,在script标签创建的时候会将当前script所有使用var定义的变量,在开始时就在内容中
开辟空间,并且设置变量名,但是没有赋值,当没有赋值时,值就是undefined
3.let a =1 let会强制要求在未定义之前禁止使用该变量
var/let/count之间的区别
声明位置和作用域:
`var`声明的变量具有函数作用域或全局作用域,取决于其声明位置;
`let`和`const`声明的变量具有块级作用域,只在声明所在的代码块内有效。
变量提升:
`var`声明的变量存在变量提升现象,即在声明之前使用该变量不会报错,但此时变量的值为`undefined`;(变量提升:将变量声明提升到它所在作用域的最开始的部分)
`let`和`const`声明的变量不进行变量提升,如果在声明前使用会抛出错误。
重复声明:
`var`声明的变量可以在同一作用域中重复声明,后声明的同名变量会覆盖之前的声明;
`let`和`const`声明的变量不允许在同一作用域中重复声明。
变量赋值:
`let`声明的变量可以改变其值,但类型不能改变;
`const`声明的常量一旦赋值后就不能再修改,且必须立即初始化。
全局属性:
使用`var`声明的变量会成为浏览器的全局对象(如`window`)的属性
而`let`和`const`声明的变量不会自动成为全局对象的属性。
cosnt 声明必须定义, 不能重复声明 , 基础数据类型不能重复声明 ,复杂数据类型的话 不能改变引用地址,可以改变里面的值 会产生局部作用yu 没有变量提升
let 可以声明,使用的时候再定义, 产生局部作用于 没有变量提升
变量名特征
1、变量名必须使用合法字符,不能使用数字开始,并且变量名只能包含字母、数字、下划线、$。
2、变量名必须使用驼峰式命名法,第一个字母不用大写,后续的单词首字母大写,如果临时变量尽量使用下划线起始
3、不能使用js中关键字和保留词
4、禁止定义与window属性同名的变量,当然使用let时不遵循
5、如果有多个变量,变量值相等可以使用连等赋值 var a=b=3;当变量需要预先定义时可以使用,分隔
6、常量名定义时使用全部大写字母,单词使用下划线(_)分隔
数据类型
1.数值类型
var a=1;//正整型
var a1=-1//负整型
var a2=1.2//浮点型 在js中所有的浮动型运算都会转换为二进制运算,因此在转换计算后会产生误差
var a3=065; //0起头是8进制,在ES6中禁止使用
var a4=0xFF;//16进制
var a5=1.23e+2;//科学计数法 1.23*10**2 10的2次幂
var a6=1.23e-2;//10的负二次幂
数值是有限制长度,当超出数值长度限制时,无法运算了
当数字超限时,使用 数字n+数字n
2.字符类型(字符串不允许出现相同的引号)
var b="a";
var b1='a';
var b2=`a`[反引号:支持文本内容的书写,同时也支持多行文本内容的书写(支持敲回车),也支持变量的解析( ${变量名})和表达式]
3.布尔类型
var c=true;//真
var c1=false;//假
4.未定义类型
第一种:var d=undefined;//不管原来存储的是什么值都会覆盖为undefined
第二种: var d1;//仅开辟内存的空间并且命名,因此如果已经开辟 将不执行
5.空值null
var e=null; 值 这个值的类型是object
解决内存泄漏,处理对象引用关系
empty空值 与null undefind不同
6.对象类型 object
var f={a:1,b:2};
类型别名(会自动指出能判断的类型有哪些)
bigint(大整型)、 string 、 number、 boolean、 undefined、 object、 function、(函数)、 symbol(唯一类型)
所有的函数就是function类型
typeof 可以检测基本数据的类型
基本数据类型在js中的特殊性
1.一定是自己所属类的实例
2.但是不一定是对象数据类型的
//字面量创建方式(也是Number类的实例,也可以调用内置的公有方法)
let n = 10;
console.log(typeof n)//number
console.log(n.toFixed(2))//10.00
//构造函数创建模式(创建出来的实例是对象类型的)
let m = new Number("10")
console.log(typeof m)//object
console.log(m.toFixed(2))//10.00
数据类型的检测
/*
typeof
优点:typeof是操作符,可以判断基本数据类型
(返回值有:undefined,number,string,boolean,object,function)
缺点:不能判断出null,object,Array,因为它们的返回值都是object,Array属于object。(在 JS 中的二进制数据储存中,二进制前三位为 000 代表引用类型) (typeof无法细分object)
typeof判断是由他们前三位的二进制决定的,null由于它的二进制都是0,object的前三位为0,所以typeof判断出它们都是object
*/
/*
instanceof
用来检测某个实例是否属于这个类
属于返回true 不属于返回false
要求检测的实例必须是对象数据类型,基本数据类型的实例无法基于它检测
*/
数据类型转换
第一种:强制类型转换
使用的方式是:构造函数转换方式
只有一个构造函数,所有构造函数名字一样:constructor
var a = 1;
console.log(String(a))会调用String类中的构造函数
1.转换成字符串型String
- 数值、布尔值、undefined、null都会转换为对应的字符串 1–>“1” true–>“true” undefined–>“undefined” null–>“null”
- 对象转换为 “[object Object]” 所有对象全部转换为这个字符串
数组使用join方法无参数,也就是将数组中的元素使用逗号为分隔符连接为一个字符串
[1,2,3]-->"1,2,3"
[1]-->"1"
[]-->""
console.log([1].join(''));//1
console.log(["1"]==1);//true
console.log(["1"]=="1");//true
console.log([]== "");//true
2.转换成数值型Number
字符串转换为数值类型,如果在字符串中有非数值出现转换为NaN,除此以外都会转换为数值
console.log(Number("3.14e+2")); 314
console.log(Number("067"));//代表十进制 并不是八进制 67
console.log(Number(0xFF));//16进制 255
console.log(Number("3a")); NaN
console.log(Number("0x3a"));//16进制 58
空字符串转换为数值是0 ""--->0
布尔值转换为数值类型, true--->1 false--->0
null转换为数值型 null-->0
undefined 转换为数值型 undefined-->NaN
所有的对象转换为数值型都是 NaN
所有的数组转换为数值型,都会先隐式转换为字符型,后转换为数值型
3.转换为布尔型Boolean
只有0," ",undefined,null,NaN,false 转换为Boolean值是false,其他转换后都是true
数组遇到强制转换为布尔值,不优先隐式转换为字符串,因为数组本身也是引用类型,所有引用类型转换为布尔值都是true
console.log(Boolean([]))//true
console.log(Boolean(""));//false
console.log(Boolean(0));//false
4.转换为对象类型Object
任何类型转换为对象时,都是该类型的对象类型
数值型,布尔值,字符串不是对象类型,不能使用
语法,不能使用对象的方法
创建了三种对象:数值对象,布尔值对象,字符串对象,把三种对象类型的方法中映射到数值,布尔值,字符串中 ,就可以使用对应的方法—目的让栈中存储的数据可以调用方法
任何类型都有对应的对象类型
console.log(Object(1));数值对象型//Number {1}
var a="1"
var b=String(a) b就是字符串对象类型 就可以使用里面的方法
console.log(Object(b))//String {'1'}
5.转换为唯一Symbol(只能放字符串和数值)
当使用值类型不是数值或者字符串时,会隐式转换为字符串(使用强制字符串类型转换)
除此之外全部直接放入
6.不能转换为undefined和null
第二种:非强制类型转换
1.转为字符串
toString() 所有类型都有这个方法 因为所有类型都是继承于Object,所以所有类型都有这个方法
var b=true;
console.log(b.toString())// "true"
var o={a:1,b:2}; console.log(o.toString());//[object Object]
var arr=[1,2,3];
console.log(arr.toString())"1,2,3"
数组和对象可以直接.toString()方法,数字不可以—因为变量命名不可以以数字开头
[1,2].toString()
console.log({a:1,b:2}.toString())//[object Object]
console.log(1.toString());(报错)//数值是不能直接使用toString,必须使用变量调用
console.log(true.toString())//true
数值类型转换为字符串**
将数字转成不同进制的数字,()里面不放数字就是十进制
数值在使用toString() 重新修改了这个方法 进制限制为2-36,这个参数需要输入的是正整数2-36之间
var n=255;
// console.log(n.toString());//"255"(10进制)
console.log(n.toString(2))//"11111111"(2进制)
// console.log(n.toString(16))//"ff"(16进制)
console.log(n.toString(8))//"377"(8进制)
**toFixed **返回指定小数部分数量的字符串
会四舍五入 小数点后面只有6才会进位
var a=3;//参数必须是0-100之间的整数
console.log(a.toFixed(1));//3.0
自动四舍五入
var a=3.256;
console.log(a.toFixed(2));//3.26
toPrecision转换为科学技术法
toExponential 完全科学计数法
var a=30000;
如果有整数转换为科学技术法,保留两位数字(参数是3 就保留 三位数字)
console.log(a.toPrecision(2));//3.0e+4
console.log(a.toPrecision(3));//3.00e+6
var a=0.03456;
如果是小数点后,保留两个非零数值(参数是3 就保留 三位非零数字)
console.log(a.toPrecision(2));//0.035
console.log(a.toPrecision(3))//0.0346
var a=0.032564
var b=3500;
console.log(a.toExponential(3));//3.256e-2
console.log(b.toExponential(3));//3.500e+3
toLocaleString转换为本地指定字符串
var a=3;
console.log(a.toLocaleString());//3
还可以使用+的字符串拼接作用
2.转为数值
parseInt():将字符串转为数值,
parseInt会自动将第一个参数隐式转换为字符串 第二个参数是 进制
将字符串看为转换后进制字符
自动转换为10进制
console.log(parseInt("1010",2))//10
console.log(parseInt("ff",16))//255
console.log(parseInt("23a"))//23 第一个要是数字
console.log(parseInt("a23"))//NaN 第一个是字母就是NaN
console.log(parseInt("aa",16))//170
console.log(parseInt({a:1,b:2},2))//对象不能转换 NaN
//数组可以转换 因为数组会先转换为字符串 在转换为数值
console.log(parseInt([1,2,3],2))//1
parseFloat()
针对的是字符串转换为浮点数,如果是非字符串则会隐式转换为字符串后在转换 (仅作为转换十进制的浮点数)
console.log(Number("1.23"))//1.23
console.log(Number("1.00"))//1
console.log(Number("1.67"))//1.67
console.log(Number(true))//1 针对的是字符串转换为浮点数,如果是非字符串则会隐式转换为字符串后再转换
// console.log(parseFloat("1.23.4"));//1.23
非加法运算也可以隐式转换为数值
var a4='123'
console.log(a4)
console.log(typeof a4)
// console.log(a4*1)
// console.log(typeof (a4*1))//number
console.log(a4/1)
console.log(typeof (a4/1))//number
算术运算符
当运算含有小数的值时,要考虑因为js对于二进制小数运算的偏差会造成结果错误
+运算符
使用:一个是运算,一个是连接(有字符串的时候)
- 如果+ 两端其中有一个字符串时,则会将另一端转换为字符串(隐式转换)连接在一起
console.log("a"+4)// a4
console.log("a"+true)// atrue
console.log("a"+undefined)// aundefined
console.log("a"+null)// anull
console.log("a"+{a:1,b:2})// a[object Object]
console.log("a"+[1])// a1
console.log(3+"")// "3"
console.log([5]+"")// "5"
- 数组如果没有强制转换为布尔值时都会隐式转换为字符串
console.log([]+3);// "3"
console.log([]+true);// true
console.log([1]+undefined); 1undefined
console.log([1]+null); 1null
console.log([1]+4); 14
console.log([1]+[2]) 12
- 对象如果没有强制转换为数值或者布尔值,隐式转换优先转换为字符串
console.log(3+{a:1})//3[object Object]
console.log({}+3)//[object Object]3
- 将另一端转换为数值
console.log(2+true) // 3
console.log(3+undefined)// NaN
console.log(3+null);// 3
- 全部隐式转换为数值
console.log(true+null); //1
console.log(true+undefined);// NaN
var b; // 是undefined
console.log("a"+b);aundefined
**-,*,/, %(取模,取余), (求幂)
都会自动隐式转换为数值运算
console.log([5]-2) // 3
console.log("56"-[21]) // 35
console.log("a3"-true); //NaN
console.log([2]*2) // 4
console.log(7/2)// 3.5
console.log(7%2) // 1
console.log(3**2) // 3的2次方 9
赋值运算符
赋值运算符优先级极低
1. += 运算 符遵照+运算符运算,会自动隐式转换为对应的类型,比如字符串
var str=[1.2];
str+=3;
console.log(str);//"1.23"
var num=3;
num+="";
console.log(num) //"3"
var arr=[1,2,3,4];
arr+="";
console.log(arr)//"1,2,3,4"
-= = /= %= 都会转换为数值运算**
var a=5;
a-=3;
console.log(a) //2
var arr=[10];
arr**=2;
console.log(arr)// 100
2.=赋值
所有运算符都返回一个值
var a="3";
var b= a+=2; // a="32"
var b=(a+=2)+5;
console.log(a,b) // a="322" b"3225"
一元运算符
实现++运算时,都是隐式转换为数值然后运算的
var arr=[1];
arr++;
console.log(arr)// 2
var arr=[];
arr++;
console.log(arr)// 1
var n="3";
n++;
console.log(n);// 4
var a=1;
console.log(a++)// 1
如果使用++在后,先返回变量再+1
如果使用++在前,先+1,再返回值
var a=1;
console.log(a++);// 1
console.log(++a);// 3
var a=1;
var b=a++; // 1
var c=++a; // 3
console.log(a,b,c);//3,1,3
var a=1;
if(a--){
console.log('aaa');//会运行
}
if(--a){
console.log("bbb")// 不会运行
}
var i=2;
// 2 + 3 +3 + 4 + 5 +5 + 6
var s=i+ ++i +i+ ++i+ ++i +i+ ++i;
console.log(s,i);// 28 6
var a=2;
var s=0;
// 0 + 2 + 3 - 1 - 2 + 0*2+2
s+=s++ +a++ +a-- -s-- -a++ +s*2+ (s+=2);
console.log(s,a);//4 3
遇到乘法 ++的优先级高于 * 最好将*与++分开
当一个式子有两次赋值,只取最后一次赋值
var s=0;
s+=++s 其中有两次赋值 但是只做最后一次的赋值
通过优先级判断 最后一次赋值
++s的优先级比s+=1高 所以++s的赋值不做数-->s还是0
++s的值被s+=1覆盖了 最终结果是 s+=1 -->s=1
关系运算符
两个等号(==)(会隐式转换):如果两边都是字符串,转换unicode编码比较,如果一侧不是字符串,转换为数值比较
< > <= >= == === != !== 关系运算符返回的结果是布尔值
console.log("aa"<"ab") true
console.log("一"<"二") true
console.log(1<"a") false
console.log(true>0) true
console.log([2]>1) true
**三个等号(===)😗*先判断类型是否相同,然后再判断值是否相同
都是true
console.log(""==false);
console.log(""==0);
console.log(false==0);
如果判断是否==0或者==false
"0" [] ["0"] [0] false 0 ==0
"0" [] ["0"] [0] false 0 ==false
如果判断是否==""
false "" 0 []
只有这两个是相等关系
console.log(undefined==null);
任何内容不等于NaN
//以下全是true
console.log([]=="")
console.log([]==false);
console.log([]==0);
console.log(""==false)
console.log(""=="")
console.log(""==0)
console.log(["0"]==0)
console.log([0]==0)
console.log([0]==false)
console.log(["0"]==false)
与=的区别
1、对于string,number等基础类型,==和===是有区别的
不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等
同类型比较,直接进行“值”比较,两者结果一样
2、对于Array,Object等高级类型,==和===是没有区别的
3、基础类型与高级类型,==和===是有区别的
对于==,将高级转化为基础类型,进行“值”比较
因为类型不同,===结果为false
隐式转换 先判断两侧是不是字符串,如果其中一侧不是字符串,优先转换为数值比较
console.log(1=="1");//true
console.log(true=="true");//false
console.log(true=="1"); //true
console.log("a"==["a"]) // true
数组和对象会隐式转换为字符串
console.log([]=="") // true
console.log([0]==""); //false
console.log(Number([0])==""); // true
!取反 a=true 则!a=false
==的隐式转换规则
1.对象和布尔值进行比较时,对象先转换为字符串,然后再转换为数字,布尔值直接转换为数字
[] == false
结果是true,[]转换为字符串’’,然后再转换为数字0,false转换为数字0
2.对象和字符串进行比较时,对象转换为字符串,然后两者进行比较
[1,2,3] == ‘1,2,3’
结果是true [1,2,3] 转化为 ‘1,2,3’
3.对象和数字比较时,对象转化为字符串,然后转换为数字,再和数字进行比较
[1] == 1
结果为true,[1]转换为’1’再转换为1
4.字符串和数字比较时,字符串转换为数字
‘1’ == 1
5.字符串和布尔值进行比较时,二者全部转换成数值再比较
‘1’ == true
6.布尔值和数字进行比较时,布尔转换为数字
==的转换原理
在转换的时候会先调toPrimitive这个方法 ,如果这个方法不能实现的话再调valueof 最后再调用 toString (内置的 自己调用的)
**==!**就是强制隐式转换为布尔值然后取反
console.log([]==![]);false//-->[]==false
(false,没有触发强制转换给Boolean转的话为false)
console.log([]==[]);false
数组或者对象在不强制转换时,都是引用类型,引用类型的地址不同,所以不相等
console.log({a:1}=="[object Object]");//true
console.log({b:2}=="[object Object]");//true
console.log({a:1}=={b:2});false //{a:1}和{b:2}都是引用类型,引用类型的地址不同
如何判断是不是NaN
不能使用==判断NaN
NaN 最特殊的地方就是,我们不能使用相等运算符 == 和 === 来判断一个值是否是 NaN,因为 NaN == NaN 和 NaN === NaN 都会返回 false。
不进行隐式转换,首先判断其类型是否相等,然后判断值是否相等
Object.is()方法用来判断两个值是否相等,它接收两个参数,分别是需要比较的两个值
console.log(Object.is(3,3)) // true
console.log(Object.is("3",3))//false
console.log(Object.is(Number("3"),3))//true
console.log(Object.is(Number("a"),NaN));//Object.is(value1,value2)等同于===比较 true
console.log(Object.is("a",NaN));//Object.is(value1,value2)等同于===比较 false
isNaN()
函数的机制是尝试将传入的参数转换为数字。如果转换成功,函数返回 false
;如果转换失败,则返回 true
。
这意味着 isNaN()
实际上是在检查参数是否不能被转换为数字,而不是直接检查参数是否等于 NaN
。
Number.isNaN() 方法用于判断传递的值是否为 NaN,并且检查其类型是否为 Number,如果值为 NaN 且类型为 Number,则返回 true,否则返回 false。
会自动隐式转换
console.log(isNaN("a"));ture//这个里面的值隐式转换为数值后是否是NaN,如果是NaN返回true
不会自动隐式转换,只判断值是不是NaN,如果值不是NaN返回fasle,如果值不是数值返回false
Number.isNaN();//false
console.log(Number.isNaN("a")) // false
console.log(Number.isNaN(Number("a"))) // true
console.log(Number.isNaN(3)) // false
逻辑运算符
*&& || 返回 值
!返回布尔值
&&(与/且)
会将与运算符两端的值隐式转换为布尔值,并且根据返回的布尔值对应的值返回
true && true true
true && false false
false && true false
false && false false
如果遇到一个false,直接返回这个false对应的值
如果遇到两个true,返回第二个true对应的
var a=3;
` var b=a-1 && a; 要学习这种写法 高级 `
和上面的意义一样
if(a==1){
b=0;
}else{
b=a;
}
var obj={a:1};
`obj && obj.a && delete obj.a;`
if(obj && obj.a) delete obj.a
`var b=--a && a;`
if(a!==1){
b=a;
}else {
b=0;
}
如果长度为0时,返回0,否则返回最后一个元素,删除最后一个元素
var arr=[1,2,3,4];
var item=arr.length && arr.pop();
console.log(item)
var arr=[1,2,3,4];
`arr && arr.pop() && console.log(arr)`
||运算符(或)
true || true 返回true 返回第一个true
true || false 返回true 返回第一个true
false || true 返回true 返回第二个true
false || false 返回 false 返回第二个false
不是这6个值 false 0 "" undefined null NaN
可以进入这个条件
if(a){
b=a;
}else{
b=5;
}
例1:
var o;
`o = o || {a:1};
o || (o={a:1}) 学习这种写法`
例2:
var a=3;
var b;
a>10 || (b=2);
反条件 当不满足||前面的条件时才满足后面的条件
||后的条件需要用括号括起来
if(a>10){
}else{
b=2;
}
==! 取反 默认隐式转换为布尔值,他的优先级非常高
var a=[];
//6种值 false 0 “ ” undefined null NaN 可以进入下面的条件
if(!a){
console.log("aaa")
}
//undefined null 时
if(a!==undefined){
console.log("aaa","--1")
}
//falese "" "0" 0 [] ["0"] [0] 时
if(a==0){
console.log("aaa","--2")
}
//falese "" "0" 0 [] ["0"] [0] 时
if(a==false){
console.log("aaa","--3")
}
//false "" 0 [] 时
if(a==""){
console.log("aaa","--4")
}
//false 时
if(a!==false){
console.log("aaa","--5")
}
var bool=false;
// //取反赋值
bool=!bool;
console.log(bool);//true
用在开关
var bool=false;
document.onclick=function(){
// 开关
bool=!bool;
console.log(bool)
}
位运算符
& (与) 二进制运算
<script>
1&1=1
0&1=0
1&0=0
0&0=0
10&6=2 --> 1010&0110=0010
--> 1010
0110 结果--> 0010 (上下对应 均为"1",结果为1
不均为"1",结果为0)
console.log(4&5); //4
100
101
100=4
任意值 & 2**n-1 ---> 任意值%2**n
</script>
| 或运算
0 | 0 =0
1 | 0 =1
0 | 1=1
1 | 1=1
console.log(8 | 7)//15
1000
0111
1111=15
有一个为"1",结果为1
两个均为"0",结果为0
^ (异)运算用于加密
<script>
1^1=0
0^0=0
1^0=1
0^1=1
var num=34567
var n=num^23455
56472 加密后字符
console.log(56472^23455)//34567
console.log(n)//56472
</script>
~ +1取负
向下取整 不会四舍五入
转换为二进制计算,小数会自动舍弃
将任意类型转换为数值型,如果无法转换则转换为0
var a=3;
a=~a;//-4
a=~a;//3
var a="a";
console.log(~~a);// 0
var a="1";
console.log(~~a) // 1
if(!~~a){
}
//~~ (取整)将任意类型转换为数值型,如果无法转换则转换为0
var b=2.345;
console.log(~~b);//2
var c="3";
console.log(~~c)//3
二进制 << >> >>>
1、左移“<<” 不分正负数,低位补0
0010 <<1 = 001(即:2<<1 = 1)可以看作:2 * 2**1 = 4
1010 << 2 = 10(即:10<<2 = 2)可以看作:10 * 2**2 = 40
(直接去掉前两位 若需要补满四位则在后面补两位)
-10<<2 = -40(即:-10<<2 = 2)可以看作:-10 * 2**2 = -40
-1010 -101000
-15<<2 = -60(即:-15<<2 = 2)可以看作:-15 * 2**2 = -60
-1111 -111100
(注!! 移出的位数舍去,空缺的用0补齐)
需要补齐八位字节在移位
26-->11010 -->补齐-->00011010
26<<1 -->00110100 -->52
26<<2 -->00011010<<2 -->01101000 -->104
负数以补码的形式存在
-26原码 -->10011010
-26补码 -->11100110
-26<<1 -->11100110<<1 -->11001100->转原码 -->10110100->-52
2、右移“>>” 如果该数为正,则高位补0;为负数,则高位补1
0010 >> 1 = 001(即:2>>1 = 1)可以看作:2 / 2**1=1
1010 >> 2 =10(即:10>>2=2)可以看作:10 / 2**2 = 2
(直接去掉后两位 若需要补满四位则在前面补两位)
相当于,每右移一位,对应的十进制数整除2
-10>>2 = -3(即:-10>>2 = -3)可以看作:-10 / 2**2 - 1 = -3
-15>>2 = -4(即:-15>>2 = -4)可以看作:-15 / 2**2 - 1 = -4
相当于,每右移一位,对应的十进制数整除2再减去1
(注!!! 整数右移:左侧补0 负数右移:左侧补1)
26>>1 -->00011010>>1 -->00001101
13>>1 -->00001101>>1 -->00000110
若小数,小数部分被省略
-26>>1 -->11100110>>1 -->11110011->转原码 -->10001101
3.">>>" 无符号右移
整
正数右移:左侧补0
负数右移:左侧补0
补充内容:::
原码:14-->00001110
-21-->10010101
补码=反码+1
-21补-->11101011
反码=补码+1
-7补-->11111001->转反码-->11111000->转原码-->10000111
8位二进制数能表示的十进制范围:-128~+127
若超出此范围,则会造成溢出,只能用两字节16位二进制表示
0补-->00000000
-128补-->10000000
正数的原码,反码,补码都一样
负数的反码 除去符号位不变 其余取反
补充:什么情况下是NaN
第一个情况:
当一个非数字在进行 减乘除 运算时,得到的结果就是NaN
第二种情况:
当一个非数字或者无法隐式转换为数字的值 进行 减乘除 运算时 得到的结果就是NaN
注意:加法 不会转为NaN,因为加法 会将值隐式转换为 number 类型