普里亚普斯 学习站

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1413 | 回复: 6

JavaScript 笔记

[复制链接]

15

主题

76

回帖

1138

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1138
发表于 2021-8-31 19:00:46 | 显示全部楼层 |阅读模式
ES5 最为广泛

ES6 次之,主流浏览器目前推荐

ES 借鉴了 C语言 和 类C语言如Java/Perl

ES 区分大小写,变量 test 和 Test 是不同的变量,type不能作为函数名(他是个变量),而Type可以;

标识符,就是变量、函数、属性或函数参数的名称。

标识符第一个必须是字母、下划线或美元符号$开始

推荐用驼峰命名法(首字母小写、后面单词首字母大写)

关键字、保留字、true、false和null不能作为标识符

[mw_shl_code=javascript,false]// 单行

/*
双行
*/[/mw_shl_code]注释就这两种

严格模式(ES5 新增的) :是一种不同的JavaScript解析和执行模型,ECMAScript 3的一些不规范写法在这种模式下会被处理,对于不安全的活动将抛出错误。启动方式:在脚本开头的一行上加如该预处理指令:  "use strict"
目的:不破坏 ES3 语法

也可单独指定一个函数中执行严格模式:
[mw_shl_code=javascript,false]function aa(){
    "use strict"
    ...
}[/mw_shl_code]现代浏览器都支持严格模式!

语句

语句以分号结尾(不要省略)

if 最好加上大括号


变量
ES 的变量是松散的,即:可存任何类型的数据。

声明变量关键字:var、const 和 let

var:任何ES版本都能用,const 和 let 只能在 ES6 或往后版本中有;

函数内用var声明的变量,执行完函数后该变量销毁,但是函数内没有用var或其它关键字声明的变量,创建的是一个全局变量:
[mw_shl_code=javascript,false]function func(){
    var a = 'abc';     // 局部
    b = 333;      // 全局
}[/mw_shl_code]
上述代码中,a变量为局部,b为全局(不建议不用var而去声明全局变量);

一行声明多个变量:
[mw_shl_code=javascript,false]var A = 'mes', b = 1, c = true;[/mw_shl_code] 在严格模式下,不能定义名为eval和arguments的变量,否则会导致语法错误。

var 声明的提升?
[mw_shl_code=javascript,false]function foo() {
  console.log(age);
  var age = 26;
}
foo();  // undefined[/mw_shl_code]

var 声明的变量 age 会自动提升到函数作用域顶部,即:
[mw_shl_code=javascript,false]function foo() {
  var age;
  console.log(age);
  age = 26;
}
foo();  // undefined[/mw_shl_code]

也就是把所有变量声明都拉到函数作用域的顶部。

let 和 var 的区别
let和var差不多,但是其 let 声明的范围是块作用域,var是函数作用域。
[mw_shl_code=javascript,false]if (true) {
  var name = 'Matt';           // var 是函数作用域,所以这里声明的name是全局作用域,如果在函数中就是函数作用域
  console.log(name); // Matt
}
console.log(name);   // Matt

if (true) {
  let age = 26;         // let 声明的范围更小,其仅限于 块 中,这里是 if 块,出了该块变量age就被销毁
  console.log(age);   // 26
}
console.log(age);     // ReferenceError: age没有定义[/mw_shl_code]块作用域是函数作用域的子集,因此适用于var的作用域限制同样也适用于let。

let 不允许同一个块作用域中多次声明,而var可以!
嵌套不同块中使用的let声明倒是不会报错,因为:JavaScript引擎会记录用于变量声明的标识符及其所在的块作用域,而同一个块中没有重复声明:
[mw_shl_code=javascript,false]let age = 30;
console.log(age);    // 30
if (true) {
  let age = 26;
  console.log(age);  // 26
}[/mw_shl_code] 混用let和var声明同一个变量同样报错!

let 声明的变量不会在该作用域中被提升!!
[mw_shl_code=javascript,false]// age不会被提升
console.log(age); // ReferenceError:age没有定义
let age = 26;[/mw_shl_code]var的前面说过了,会提升~

全局中用 var 声明的变量会编程 window对象的属性,而 全局中用 let 声明的变量不会;
[mw_shl_code=javascript,false]let age = 26;
console.log(window.age);  // undefined[/mw_shl_code]这里的age变量为全局作用域,因此,需要避免在全局中再次声明同名的 age 变量;

let 作用域是块,所以不可能检测前面是否已经使用let声明过同名的变量,同时也不可能在没有声明的情况下声明它:
[mw_shl_code=javascript,false]<script>
  var name = 'Nicholas';
  let age = 26;
</script>

<script>
  // 假设脚本不确定页面中是否已经声明了同名变量
  // 那它可以假设还没有声明过

  var name = 'Matt';
  // 这里没问题,因为可以被作为一个提升声明来处理
  // 不需要检查之前是否声明过同名变量

  let age = 36;
  // 如果age之前声明过,这里会报错
</script>[/mw_shl_code] 使用 try/catch 或 typeof 也不能解决,因为条件块中let声明的作用域仅限于该块。
[mw_shl_code=javascript,false]<script>
  let name = 'Nicholas';
  let age = 36;
</script>

<script>
  // 假设脚本不确定页面中是否已经声明了同名变量
  // 那它可以假设还没有声明过

  if (typeof name === 'undefined') {
    let name;
  }
  // name被限制在if {} 块的作用域内
  // 因此这个赋值形同全局赋值
  name = 'Matt';

  try (age) {
    // 如果age没有声明过,则会报错
  }
  catch(error) {
    let age;
  }
  // age被限制在catch {}块的作用域内
  // 因此这个赋值形同全局赋值
  age = 26;
</script>[/mw_shl_code] ES6声明的let关键字,不能依赖条件声明模式(这是好事,因为条件声明时一种反模式,其会让程序变得复杂难理解,如果你使用了,说明你的代码有更好的替换方式)

let之前的var,for循环定义的变量会渗透到循环体外:
[mw_shl_code=javascript,false]for (var i = 0; i < 5; ++i) {
  // 循环逻辑
}
console.log(i); // 5[/mw_shl_code]而用let就不会,因为let作用域仅限块中(这里是for块)
[mw_shl_code=javascript,false]for (let i = 0; i < 5; ++i) {
  // 循环逻辑
}
console.log(i); // ReferenceError: i没有定义[/mw_shl_code]var在for中最常见的问题如下:
[mw_shl_code=javascript,false]for (var i = 0; i < 5; ++i) {
    setTimeout(() => console.log(i), 0)
}
// 你可能以为会输出0、1、2、3、4
// 实际上会输出5、5、5、5、5[/mw_shl_code]原因:在退出循环时,迭代变量保存的是导致循环退出的值:5。在之后执行超时逻辑时,所有的i都是同一个变量,因而输出的都是同一个最终值。

而在使用let声明迭代变量时,JavaScript引擎在后台会为每个迭代循环声明一个新的迭代变量。每个setTimeout引用的都是不同的变量实例,所以console.log输出的是我们期望的值,也就是循环执行过程中每个迭代变量的值。

[mw_shl_code=javascript,false]for (let i = 0; i < 5; ++i) {
    setTimeout(() => console.log(i), 0)
}
// 会输出0、1、2、3、4[/mw_shl_code]这种每次迭代声明一个独立变量实例的行为适用于所有风格的for循环,包括for-in和for-of循环。

const 常量声明
const 与 let 很类似,区别是 用const 声明的变量必须同时初始化(即赋值),且尝试修改会导致运行时错误!

const 声明的常量的作用域也是块作用域!
[mw_shl_code=javascript,false]// const声明的作用域也是块
const name = 'Matt';
if (true) {
  const name = 'Nicholas';
}
console.log(name); // Matt[/mw_shl_code]
const声明的限制只适用于它指向的变量的引用。换句话说,如果const变量引用的是一个对象,那么修改这个对象内部的属性并不违反const的限制,如下:
[mw_shl_code=typescript,false]const person = {};
person.name = 'Matt';  // ok[/mw_shl_code]
不能用const作为循环中的迭代变量:
[mw_shl_code=javascript,false]for (const i = 0; i < 10; ++i) {} // TypeError:给常量赋值[/mw_shl_code]因为:迭代变量 i 会自增
但是如果你只想用const声明一个不会被修改的for循环变量,那倒是可以的,也就是说,每次迭代只是创建一个新变量。这对for-of和for-in循环特别有意义,如下代码:
[mw_shl_code=javascript,false]let i = 0;
for (const j = 7; i < 5; ++i) {
  console.log(j);
}
// 7, 7, 7, 7, 7

for (const key in {a: 1, b: 2}) {
  console.log(key);
}
// a, b

for (const value of [1,2,3,4,5]) {
  console.log(value);
}
// 1, 2, 3, 4, 5[/mw_shl_code]

声明的风格与最佳实践
行为怪异的var被let修复了,实际中,我们应该:

不使用var:因为变量有了明确的作用域、声明位置,以及不变的值。

cconst优先、let次之:用const可在运行时强制保持变量不变,提前发现不合法赋值操作~

数据类型
简单类型(原始类型)6种:Undefined/Null/Boolean/Number/String/Symbol。Symbol(符号)是ES6新增的。

复杂类型:Object(对象)。无序名值对的集合。因在ES中不能自定义数据类型,所有值都可用上述7种数据类型之一表示。

typeof 操作符
确定任意变量的数据类型,对一个值用type操作符会返回如下字符串之一:

"undefined"表示值未定义;
"boolean"表示值为布尔值;
"string"表示值为字符串;
"number"表示值为数值;
"object"表示值为对象(而不是函数)或null;
"function"表示值为函数;
"symbol"表示值为符号。
例子:
[mw_shl_code=javascript,false]let message = "some string";
console.log(typeof message);    // "string"
console.log(typeof(message));   // "string"
console.log(typeof 95);         // "number"[/mw_shl_code]注意:因为typeof是一个操作符而不是函数,所以不需要参数(但可以使用参数)

注意:typeof在某些情况下返回的结果可能会让人费解,但技术上讲还是正确的。比如,调用typeof null返回的是"object"。这是因为特殊值null被认为是一个对空对象的引用。

注意:严格来讲,函数在ECMAScript中被认为是对象,并不代表一种数据类型。可是,函数也有自己特殊的属性。为此,就有必要通过typeof操作符来区分函数和其他对象。

Undefined 类型
其值只有一个,就是特殊值undefined。

当使用var或let声明了变量但没有初始化时,就相当于给变量赋予了undefined值。即:默认情况下,任何未经初始化的变量都会取得undefined值。

[mw_shl_code=javascript,false]let message = undefined;
console.log(message == undefined); // true[/mw_shl_code]变量message显式地以undefined来初始化。但这是不必要的。

注意:一般来说,永远不用显式地给某个变量设置undefined值。字面值undefined主要用于比较,而且在ECMA-262第3版之前是不存在的。增加这个特殊值的目的就是为了正式明确空对象指针(null)和未初始化变量的区别

注意,包含undefined值的变量跟未定义变量是有区别的:

[mw_shl_code=javascript,false]let message;    // 这个变量被声明了,只是值为undefined

// 确保没有声明过这个变量
// let age

console.log(message); // "undefined"
console.log(age);     // 报错[/mw_shl_code]对未声明的变量,只能执行一个有用的操作,就是对它调用typeof。(对未声明的变量调用delete也不会报错,但这个操作没什么用,实际上在严格模式下会抛出错误。)

在对未初始化的变量调用typeof时,返回的结果是"undefined",但对未声明的变量调用它时,返回的结果还是"undefined",这就有点让人看不懂了:
[mw_shl_code=javascript,false]let message; // 这个变量被声明了,只是值为undefined

// 确保没有声明过这个变量
// let age

console.log(typeof message); // "undefined"
console.log(typeof age);     // "undefined"[/mw_shl_code]

无论是声明还是未声明,typeof返回的都是字符串"undefined"。逻辑上讲这是对的,因为虽然严格来讲这两个变量存在根本性差异,但它们都无法执行实际操作。

注意:即使未初始化的变量会被自动赋予undefined值,但我们仍然建议在声明变量的同时进行初始化。这样,当typeof返回"undefined"时,你就会知道那是因为给定的变量尚未声明,而不是声明了但未初始化。

undefined是一个假值。因此,如果需要,可以用更简洁的方式检测它。不过要记住,也有很多其他可能的值同样是假值。所以一定要明确自己想检测的就是undefined这个字面值,而不仅仅是假值:
[mw_shl_code=javascript,false]let message; // 这个变量被声明了,只是值为undefined
// age没有声明

if (message) {
  // 这个块不会执行
}

if (!message) {
  // 这个块会执行
}

if (age) {      // 这里会报错

}[/mw_shl_code]

NULL 类型
Null类型也只特殊值:null,逻辑讲,null值表示一个空对象指针,即:typeof null; 会返回"object"的原因:
[mw_shl_code=javascript,false]let car = null;
console.log(typeof car);    // "object"[/mw_shl_code]
定义将来要保存对象值的变量时,建议使用null来初始化,不要使用其他值。这样只要检测这个变量是否是null就知道该值是否在后来被赋了一个对象引用。
[mw_shl_code=javascript,false]
if (car != null) {
  // car是一个对象的引用
}[/mw_shl_code]
undefined值是由null值派生而来的,因此ECMA-262将它们定义为表面上相等!如:
[mw_shl_code=javascript,false]
console.log(null == undefined);  // true
[/mw_shl_code]

永远不要显示设置变量为undefined。而对于null,任何时候,只要变量要保存对象,而当时又暂无该对象,则要用null填充该变量。这样就可以保持null是空对象指针的语义,并进一步将其与undefined区分开来。

null是一个假值。因此,如果需要,可以用更简洁的方式检测它。
[mw_shl_code=javascript,false]
let message = null;
let age;

if (message) {
  // 这个块不会执行
}

if (!message) {
  // 这个块会执行
}

if (age) {
  // 这个块不会执行
}

if (!age) {
  // 这个块会执行
}[/mw_shl_code]

Boolean类型
True 和 False 是标识符,而不是 boolean 类型的值!

其他ECMAScript类型的值都有相应布尔值的等价形式:
[mw_shl_code=javascript,false]let messageAsBoolean = Boolean(message);[/mw_shl_code]

数据类型
转为true 的
转为false 的
Boolean true false
String 非空字符串 ""(空字符串)
Number 非0数值(包括无穷值) 0、NaN
Object 任意对象 null
Undefined N/A(不存在) undefined


Number类型
进制进制字面量表示:
[mw_shl_code=javascript,false]let intNum = 34;     // 常见的十进制
let octalNum1 = 070;  // 八进制的56
let octalNum2 = 079;  // 无效的八进制值,当成79处理
let octalNum3 = 08;   // 无效的八进制值,当成8处理
let hexNum1 = 0xA;   // 十六进制
let hexNum2 = 0x1f;   // 十六进制[/mw_shl_code]
严格模式下,上面用0开头的八进制字面量禁止!而应该以前缀 0o 开头~

定义浮点数时,数值必须有小数点,且小数点后面必须至少有一个数字。
[mw_shl_code=javascript,false]let floatNum2 = 0.1;
let floatNum3 = .1;   // 有效,但不推荐[/mw_shl_code]
因为存储浮点值使用的内存空间是存储整数值的两倍,所以ECMAScript总是想方设法把值转换为整数。小数点后面没有数字的情况下,数值就会变成整数。如果数值本身就是整数,只是小数点后面跟着0(如1.0),那它也会被转换为整数

如果某个计算得到的数值结果超出了JavaScript可以表示的范围,那么这个数值会被自动转换为一个特殊的Infinity(无穷)值。该值将不能再进一步用于任何计算。这是因为Infinity没有可用于计算的数值表示形式。

NaN
其意思是“不是数值”(Not a Number),用于表示本来要返回数值的操作失败了(而不是抛出错误)。比如,用0除任意数值在其他语言中通常都会导致错误,从而中止代码执行。但在ECMAScript中,0、+0或-0相除会返回NaN:
[mw_shl_code=javascript,false]console.log(0/0);    // NaN
console.log(-0/+0);  // NaN[/mw_shl_code]
如果分子是非0值,分母是有符号0或无符号0,则会返回Infinity或-Infinity:
[mw_shl_code=javascript,false]console.log(5/0);   // Infinity
console.log(5/-0);  // -Infinity[/mw_shl_code]

用NaN计算的表达式其都返回NaN

NaN 不等于任何,包括自己(NaN == NaN 结果为false)

判断是否为NaN用 isNaN() 函数,该函数会尝试把传入的参数转换为数值,任何不能转换为数值的值都会导致这个函数返回true
[mw_shl_code=javascript,false]console.log(isNaN(NaN));     // true
console.log(isNaN(10));      // false,10是数值
console.log(isNaN("10"));    // false,可以转换为数值10
console.log(isNaN("blue"));  // true,不可以转换为数值
console.log(isNaN(true));    // false,可以转换为数值1[/mw_shl_code]
注意:虽然isNaN不常见,但isNaN()可以用于测试对象。此时,首先会调用对象的valueOf()方法,然后再确定返回的值是否可以转换为数值。如果不能,再调用toString()方法,并测试其返回值。这通常是ECMAScript内置函数和操作符的工作方式,本章后面会讨论。

数值转换
Number()、parseInt()和parseFloat()

Number()是转型函数,可用于任何数据类型。后两个函数主要用于将字符串转换为数值。

Number:
true 转 1 ,false 转 0
数值 直接返回。
null 返回 0
undefined 返回 NaN
字符串:"-0123" 返 -123,"00.3" 返 0.3,"0xf" 返 16,"" 返0,"hello" 返 NaN(因为 Hello字符串 找不到对应的数值。)。
对象:调用 valueOf()方法,并按照上述规则转换返回的值。如果转换结果是 NaN,则调用toString()方法,再按照转换字符串的规则转换。

parseInt:
因为Number的复杂和反常,所以需要转换得到整数时优先使用 parseInt!其更专注于字符串是否包含数值。
字符串前面空格忽略,从第一个非空字符开始转换,如果不是数字、加减号,立即返回NaN,即 parseInt("") 返回 NaN。
转换过程碰到非数值即转换结束,即: parseInt("  -0855.65haha")  返回  -855
parseInt 的第二个参数指定转换为的进制,默认十进制。 parseInt("AF", 16);  返 175 (0x可以省略,即:AF 和 0xAF 都可以)
建议始终传给它第二个参数!

parseFloat:
和 parseInt 差不多,parseFloat 不忽略 第一次出现的小数点,但是第二个小数点无效,parseFloat("-026.22.99") 返 -26.22
parseFloat 只解析十进制!其他进制的解析始终返回 0,parseFloat("0xAF") 返 0

String
单双引号都合法;
字符串长度:"hello".length;

ECMAScript中的字符串是不可变的(immutable),意思是一旦创建,它们的值就不能变了。修改某个变量中的字符串时必须先销毁原始字符串;
[mw_shl_code=javascript,false]let lang = "Java";
lang = lang + "Script";[/mw_shl_code]
首先会分配一个足够容纳10个字符的空间,然后填充上"Java"和"Script"。最后销毁原始的字符串"Java"和字符串"Script",因为这两个字符串都没有用了。

转换为字符串
几乎所有值都有 toString() 方法,返回当前值的字符串等价物。
(11).toString();  返 "11"
false.toString();  返 "false"
null和undefined值没有toString()方法
toString() 一般不接受参数,但是针对 数值字符串的,可以接收底数参数(需要转化为的进制),如:(516).toString(16);  返 "204"

如果你不确定一个值是不是 null 或 undefined,可以使用 String() 转型函数,它始终会返回表示相应类型值的字符串。
如果值有toString() 方法,则使用这方法转换;因为 null 和 undefined 没有 toString() 则:
String(null); 返 "null"
String(undefined); 返 "undefined"


模板字面量
与用单、双引号不同,其保留换行符,可跨行定义字符串:
[mw_shl_code=javascript,false]console.log(`hello
,
world.`);[/mw_shl_code]

字符串插值
技术上讲,模板字面量不是字符串,而是一种特殊的JavaScript句法表达式,只不过求值后得到的是字符串。
[mw_shl_code=javascript,false]let value = 5;
let exponent = 'second';

let interpolatedTemplateLiteral = `${ value } to the ${ exponent } power is ${ value * value }`;
String("hello")[/mw_shl_code]

模板字面量标签函数
[mw_shl_code=javascript,false]function simpleTag(strings, aValExpression, bValExpression, sumExpression) {
    console.log(strings);
    console.log(aValExpression);
    console.log(bValExpression);
    console.log(sumExpression);
    return 'foobar';
}

let a = 6;
let b = 9;
let taggedResult = simpleTag`${a} + ${b} = ${a + b}`;          // simpleTag:标签函数      ${a}:里面的a在这里是标签函数表达式
console.log(taggedResult);[/mw_shl_code]
输出结果:
[mw_shl_code=text,false][ '', ' + ', ' = ', '' ]
6
9
15
'foobar'[/mw_shl_code]
因为表达式参数的数量是可变的,所以通常应该使用剩余操作符( rest operator)将它们收集到一个数组中:
[mw_shl_code=javascript,false]let a = 6;
let b = 9;
function simpleTag(strings, ...expressions) {
    console.log(strings);
    for(const expression of expressions) {
        console.log(expression);
    }
    return 'foobar';
}
let taggedResult = simpleTag`${ a } + ${ b } = ${ a + b }`;
console.log(taggedResult); // "foobar"[/mw_shl_code]

String.row 函数... 略

Symbol 类型
ES6,Symbol(符号)是原始值,且符号实例是唯一、不可变的。

作用:确保对象属性使用唯一标识符,不会发生属性冲突的危险。

听起来跟私有属性有点类似,但符号并不是为了提供私有属性的行为才增加的。相反,符号就是用来创建唯一记号,进而用作非字符串形式的对象属性。

基本用法:用 Symbol() 函数初始化,因为符号本身是原始类型,所以 typeof 对符号返回 symbol。
[mw_shl_code=javascript,false]let sym = Symbol();
typeof sym;    // symbol[/mw_shl_code]
可传入一个字符串参数作为对符号的描述,以后可通过该字符串来调试代码,但是该字符串参数描述与符号完全无关。
[mw_shl_code=javascript,false]let a = Symbol();
let b = Symbol();

a == b;   // false[/mw_shl_code]
符号没有字面量语法,这也是它们发挥作用的关键。

Symbol()函数不能与new关键字一起作为构造函数使用。这样做是为了避免创建符号包装对象,像使用Boolean、String或Number那样,它们都支持构造函数且可用于初始化包含原始值的包装对象:
[mw_shl_code=javascript,false]let myNumber = new Number();
console.log(typeof myNumber);  // "object"

let mySymbol = new Symbol(); // TypeError: Symbol is not a constructor[/mw_shl_code]
如果你确实想使用符号包装对象,可以借用Object()函数:
[mw_shl_code=javascript,false]let mySymbol = Symbol();
let myWrappedSymbol = Object(mySymbol);
console.log(typeof myWrappedSymbol);   // "object"[/mw_shl_code]

还有好多关于符号的内容,以后用到再看吧。。。

Object 类型
ES中的对象其实就是:一组数据和功能的集合。

对象通过new操作符后跟对象类型的名称来创建。

ES只要求在给构造函数提供参数时使用括号,但是不要这么做:let a = new Object;   // 省略了括号

ES中的Object也是派生其他对象的基类。Object类型的所有属性和方法在派生的对象上同样存在。

Object实例都有如下属性和方法:
  • constructor:用于创建当前对象的函数。在前面的例子中,这个属性的值就是Object()函数。
  • hasOwnProperty(propertyName):用于判断当前对象实例(不是原型)上是否存在给定的属性。要检查的属性名必须是字符串(如o.hasOwnProperty("name"))或符号。
  • isPrototypeOf(object):用于判断当前对象是否为另一个对象的原型。(第8章将详细介绍原型。)
  • propertyIsEnumerable(propertyName):用于判断给定的属性是否可以使用(本章稍后讨论的)for-in语句枚举。与hasOwnProperty()一样,属性名必须是字符串。
  • toLocaleString():返回对象的字符串表示,该字符串反映对象所在的本地化执行环境。
  • toString():返回对象的字符串表示。
  • valueOf():返回对象对应的字符串、数值或布尔值表示。通常与toString()的返回值相同。

因为在ECMAScript中Object是所有对象的基类,所以任何对象都有这些属性和方法。

前缀后缀的递增递减区别
[mw_shl_code=javascript,false]let a = 10;
let a1 = --a + 2;     // a先自减-1,得a=9,然后结果9再+2 ,计算的出的结果赋值给a1,a1 = 11
a;
a1;

let b = 10;
let b1 = b-- + 2;     // b先+2,b=12,赋值给b1,得b1 = 12,然后b再自减-1,结果:b=9
b;
b1;[/mw_shl_code]
自增自减操作符不仅限于数值,还可以是:
++"55";   返56
"AA"++;  返 NaN
"88AA"++;  返 NaN
false++;  返 1
true++;   返 2
++(.5);   返 1.5
对象:则调用其(第5章会详细介绍的)valueOf()方法取得可以操作的值。对得到的值应用上述规则。如果是NaN,则调用toString()并再次应用其他规则。变量类型从对象变成数值。
[mw_shl_code=javascript,false]let o = {
  valueOf() {
    return -1;
  }
};

o--;   // 值变成-2[/mw_shl_code]

一元加 和 减
+"66"  等同于 Number("66")


位操作符

...

布尔操作符 -- 非
对象  = false
空字符串 = true
非空字符串 = false
0 = true
非0(包括 Infinity) = false
null = true
NaN = true
undefined = true

两个感叹号 !! 可以将任意值转换为布尔值!如:  !!"blue" = true, !!NaN = false;


布尔操作符 -- 与
全true = true
有false = false
短路:true 继续、false 返回

布尔操作符 -- 或
有true = true
全false = false
短路:true 返回、false 继续


回复

使用道具 举报

0

主题

52

回帖

72

积分

注册会员

Rank: 2

积分
72
发表于 2023-5-13 05:09:32 | 显示全部楼层
admin,你是天使请来的都比吗?
回复

使用道具 举报

0

主题

52

回帖

72

积分

注册会员

Rank: 2

积分
72
发表于 2023-5-17 13:45:14 | 显示全部楼层
对楼主的崇拜如洪水滔滔
回复

使用道具 举报

2

主题

73

回帖

210

积分

中级会员

Rank: 3Rank: 3

积分
210
发表于 2023-5-19 04:06:43 | 显示全部楼层
不错的帖子
回复

使用道具 举报

2

主题

73

回帖

210

积分

中级会员

Rank: 3Rank: 3

积分
210
发表于 2023-5-25 23:58:41 | 显示全部楼层
给力啊
回复

使用道具 举报

1

主题

58

回帖

80

积分

注册会员

Rank: 2

积分
80
发表于 2023-5-27 16:58:11 | 显示全部楼层
楼主admin是我最佩服的人!
回复

使用道具 举报

0

主题

52

回帖

72

积分

注册会员

Rank: 2

积分
72
发表于 2023-6-5 21:12:11 | 显示全部楼层
厉害啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋

GMT+8, 2024-4-29 11:31 Processed in 0.042555 second(s), 19 queries .

© 2024 普里亚普斯 学习站 Powered by Discuz! X3.4 Licensed Theme by Jvmao 粤ICP备19010473号

快速回复 返回顶部 返回列表