JavaScript学习
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript学习相关的知识,希望对你有一定的参考价值。
javascript学习
这里以下内容略过,因为太简单。
- 语句
- 表达式
- 操作符
- 值与类型
- 条件和循环
- 作用域
只介绍我想说的一些内容qwq。
0.打印
console.log("content"); //控制台打印
alert("content"); //弹框方式
1.输入
age = prompt("请输入年龄: ");//弹框输入
console.log(age);
2.强制转换
var a = "42";
var b = Number( a );
console.log( a ); // "42"
console.log( b ); // 42
3.四舍五入
console.log( amount ); // 215.9784
console.log( amount.toFixed( 2 ) ); // "215.98"
4.函数
function printAmount()
console.log( amount.toFixed( 2 ) );
var amount = 99.99;
printAmount(); // "99.99"
amount = amount * 2;
printAmount(); // "199.98"
JavaScript代码并不是从上到下执行的。
而是先编译,提升函数和变量声明。
https://blog.csdn.net/weixin_33919950/article/details/92379403
https://blog.csdn.net/DDboom/article/details/104582047
比如下面这个例子:
function printAmount(amt)
console.log( amt.toFixed( 2 ) );
function formatAmount()
return "$" + amount.toFixed( 2 );
var amount = 99.99;
printAmount( amount * 2 ); // "199.98"
amount = formatAmount();
console.log( amount ); // "$99.99"
5.检查值的类型
var a;
typeof a; // "undefined"
a = "hello world";
typeof a; // "string"
a = 42;
typeof a; // "number"
a = true;
typeof a; // "boolean"
a = null;
typeof a; // "object" -- 奇怪的bug
a = undefined;
typeof a; // "undefined"
a = b: "c" ;
typeof a; // "object"
6.一些类型
a.对象
object
类型指的是一种复合值,你可以在它上面设定属性(带名称的位置),每个属性持有各自的任意类型的值。它也许是JavaScript中最有用的类型之一。
var obj =
a: "hello world",
b: 42,
c: true
;
obj.a; // "hello world"
obj.b; // 42
obj.c; // true
obj["a"]; // "hello world"
obj["b"]; // 42
obj["c"]; // true
/
var obj =
a: "hello world",
b: 42
;
var b = "a";
obj[b]; // "hello world"
obj["b"]; // 42
b.数组
一个数组是一个object
,它不使用特殊的带名称的属性/键持有(任意类型的)值,而是使用数字索引的位置。例如:
var arr = [
"hello world",
42,
true
];
arr[0]; // "hello world"
arr[1]; // 42
arr[2]; // true
arr.length; // 3
typeof arr; // "object"
c.函数
另一个你将在JS程序中到处使用的object
子类型是函数:
function foo()
return 42;
foo.bar = "hello world";
typeof foo; // "function"
typeof foo(); // "number"
typeof foo.bar; // "string"
同样地,函数也是object
的子类型 —— typeof
返回"function"
,这暗示着"function"
是一种主要类型 —— 因此也可以拥有属性,但是你一般仅会在有限情况下才使用函数对象属性(比如foo.bar
)。
d.内建类型的方法
我们刚刚讨论的内建类型和子类型拥有十分强大和有用的行为,它们作为属性和方法暴露出来。
例如:
var a = "hello world";
var b = 3.14159;
a.length; // 11
a.toUpperCase(); // "HELLO WORLD"
b.toFixed(4); // "3.1416"
e.Truthy 与 Falsy
在第一章中,我们简要地提到了值的“truthy”和“falsy”性质:当一个非boolean
值被强制转换为一个boolean
时,它是变成true
还是false
。
在JavaScript中“falsy”的明确列表如下:
""
(空字符串)0
,-0
,NaN
(非法的number
)null
,undefined
false
任何不在这个“falsy”列表中的值都是“truthy”。这是其中的一些例子:
"hello"
42
true
[ ]
,[ 1, "2", 3 ]
(数组)a: 42
(对象)function foo() ..
(函数)
f.等价性
有四种等价性操作符:==
,===
,!=
,和!==
。!
形式当然是与它们相对应操作符平行的“不等”版本;不等(non-equality) 不应当与 不等价性(inequality) 相混淆。
==
和===
之间的不同通常被描述为,==
检查值的等价性而===
检查值和类型两者的等价性。然而,这是不准确的。描述它们的合理方式是,==
在允许强制转换的条件下检查值的等价性,而===
是在不允许强制转换的条件下检查值的等价性;因此===
常被称为“严格等价”。
考虑这个隐含强制转换,它在==
宽松等价性比较中允许,而===
严格等价性比较中不允许:
var a = "42";
var b = 42;
a == b; // true
a === b; // false
在a == b
的比较中,JS注意到类型不匹配,于是它经过一系列有顺序的步骤将一个值或者它们两者强制转换为一个不同的类型,直到类型匹配为止,然后就可以检查一个简单的值等价性。
如果你仔细想一想,通过强制转换a == b
可以有两种方式给出true
。这个比较要么最终成为42 == 42
,要么成为"42" == "42"
。那么是哪一种呢?
答案:"42"
变成42
,于是比较成为42 == 42
。在一个这样简单的例子中,只要最终结果是一样的,处理的过程走哪一条路看起来并不重要。但在一些更复杂的情况下,这不仅对比较的最终结果很重要,而且对你 如何 得到这个结果也很重要。
a === b
产生false
,因为强制转换是不允许的,所以简单值的比较很明显将会失败。许多开发者感觉===
更可靠,所以他们提倡一直使用这种形式而远离==
。我认为这种观点是非常短视的。我相信==
是一种可以改进程序的强大工具,如果你花时间去学习它的工作方式。
如果你在比较两个非基本类型值,比如object
(包括function
和array
),那么你应当特别小心==
和===
的比较规则。因为这些值实际上是通过引用持有的,==
和===
比较都将简单地检查这个引用是否相同,而不是它们底层的值。
例如�,array
默认情况下会通过使用逗号(,
)连接所有值来被强制转换为string
。你可能认为两个内容相同的array
将是==
相等的,但它们不是:
var a = [1,2,3];
var b = [1,2,3];
var c = "1,2,3";
a == c; // true
b == c; // true
a == b; // false
g.函数作用域
你使用var
关键字声明的变量将属于当前的函数作用域,如果声明位于任何函数外部的顶层,它就属于全局作用域。
提升
无论var
出现在一个作用域内部的何处,这个声明都被认为是属于整个作用域,而且在作用域的所有位置都是可以访问的。
这种行为称为 提升,比喻一个var
声明在概念上 被移动 到了包含它的作用域的顶端。技术上讲,这个过程通过代码的编译方式进行解释更准确,但是我们先暂且跳过那些细节。
考虑如下代码:
var a = 2;
foo(); // 可以工作, 因为 `foo()` 声明被“提升”了
function foo()
a = 3;
console.log( a ); // 3
var a; // 声明被“提升”到了 `foo()` 的顶端
console.log( a ); // 2
警告: 在一个作用域中依靠变量提升来在var
声明出现之前使用一个变量是不常见的,也不是个好主意;它可能相当使人困惑。而使用被提升的函数声明要常见得多,也更为人所接受,就像我们在foo()
正式声明之前就调用它一样。
7.Strict模式
ES5在语言中加入了一个“strict模式”,它收紧了一些特定行为的规则。一般来说,这些限制被视为使代码符合一组更安全和更合理的指导方针。另外,坚持strict模式一般会使你的代码对引擎有更强的可优化性。strict模式对代码有很大的好处,你应当在你所有的程序中使用它。
根据你摆放strict模式注解的位置,你可以为一个单独的函数,或者是整个一个文件切换到strict模式:
function foo()
"use strict";
// 这部分代码是strict模式的
function bar()
// 这部分代码是strict模式的
// 这部分代码不是strict模式的
将它与这个相比:
"use strict";
function foo()
// 这部分代码是strict模式的
function bar()
// 这部分代码是strict模式的
// 这部分代码是strict模式的
使用strict模式的一个关键不同(改善!)是,它不允许因为省略了var
而进行隐含的自动全局变量声明:
function foo()
"use strict"; // 打开strict模式
a = 1; // 缺少`var`,ReferenceError
foo();
如果你在代码中打开strict模式,并且得到错误,或者代码开始变得有bug,这可能会诱使你避免使用strict模式。但是纵容这种直觉不是一个好主意。如果strict模式在你的程序中导致了问题,那么这标志着在你的代码中几乎可以肯定有应该修改的东西。
strict模式不仅将你的代码保持在更安全的道路上,也不仅将使你的代码可优化性更强,它还代表着这种语言未来的方向。对于你来说,现在就开始习惯于strict模式要比一直回避它容易得多 —— 以后再进行这种转变只会更难!
8.函数作为值
至此,我们已经将函数作为JavaScript中主要的 作用域 机制讨论过了。你可以回想一下典型的function
声明语法是这样的:
function foo()
// ..
虽然从这种语法中看起来不明显,foo
基本上是一个位于外围作用域的变量,它给了被声明的function
一个引用。也就是说,function
本身是一个值,就像42
或[1,2,3]
一样。
这可能听起来像是一个奇怪的概念,所以花点儿时间仔细考虑一下。你不仅可以向一个function
传递一个值(参数值),而且 一个函数本身可以是一个值,它能够赋值给变量,传递给其他函数,或者从其它函数中返回。
因此,一个函数值应当被认为是一个表达式,与任何其他的值或表达式很相似。
考虑如下代码:
var foo = function()
// ..
;
var x = function bar()
// ..
;
第一个被赋值给变量foo
的函数表达式称为 匿名 函数表达式,因为它没有“名称”。
第二个函数表达式是 命名的(bar
),它还被赋值给变量x
作为它的引用。命名函数表达式 一般来说更理想,虽然 匿名函数表达式 仍然极其常见。
9.立即被调用的函数表达式(IIFE)
在前一个代码段中,哪一个函数表达式都没有被执行 —— 除非我们使用了foo()
或x()
。
有另一种执行函数表达式的方法,它通常被称为一个 立即被调用的函数表达式 (IIFE):
(function IIFE()
console.log( "Hello!" );
)();
// "Hello!"
围绕在函数表达式(function IIFE() .. )
外部的( .. )
只是一个微妙的JS文法,我们需要它来防止函数表达式被看作一个普通的函数声明。
在表达式末尾的最后的()
—— )();
这一行 —— 才是实际立即执行它前面的函数表达式的东西。
这看起来可能很奇怪,但它不像第一眼看上去那么陌生。考虑这里的foo
和IIFE
之间的相似性:
function foo() ..
// `foo` 是函数引用表达式,然后用`()`执行它
foo();
// `IIFE` 是函数表达式,然后用`()`执行它
(function IIFE() .. )();
如你所见,在执行它的()
之前列出(function IIFE() .. )
,与在执行它的()
之前定义foo
实质上是相同的;在这两种情况下,函数引用都使用立即在它后面的()
执行。
因为IIFE只是一个函数,而函数可以创建变量 作用域,以这样的风格使用一个IIFE经常被用于定义变量,而这些变量将不会影响围绕在IIFE外面的代码:
var a = 42;
(function IIFE()
var a = 10;
console.log( a ); // 10
)();
console.log( a ); // 42
IIFE还可以有返回值:
var x = (function IIFE()
return 42;
)();
x; // 42
值42
从被执行的命名为IIFE
的函数中return
,然后被赋值给x
。
10.闭包
闭包 是JavaScript中最重要,却又经常最少为人知的概念之一。我不会在这里涵盖更深的细节,你可以参照本系列的 作用域与闭包。但我想说几件关于它的事情,以便你了解它的一般概念。它将是你的JS技术结构中最重要的技术之一。
你可以认为闭包是这样一种方法:即使函数已经完成了运行,它依然可以“记住”并持续访问函数的作用域。
考虑如下代码:
function makeAdder(x)
// 参数 `x` 是一个内部变量
// 内部函数 `add()` 使用 `x`,所以它对 `x` 拥有一个“闭包”
function add(y)
return y + x;
;
return add;
每次调用外部的makeAdder(..)
所返回的对内部add(..)
函数的引用可以记住被传入makeAdder(..)
的x
值。现在,让我们使用makeAdder(..)
:
// `plusOne` 得到一个指向内部函数 `add(..)` 的引用,
// `add()` 函数拥有对外部 `makeAdder(..)` 的参数 `x`
// 的闭包
var plusOne = makeAdder( 1 );
// `plusTen` 得到一个指向内部函数 `add(..)` 的引用,
// `add()` 函数拥有对外部 `makeAdder(..)` 的参数 `x`
// 的闭包
var plusTen = makeAdder( 10 );
plusOne( 3 ); // 4 <-- 1 + 3
plusOne( 41 ); // 42 <-- 1 + 41
plusTen( 13 ); // 23 <-- 10 + 13
这段代码的工作方式是:
- 当我们调用
makeAdder(1)
时,我们得到一个指向它内部的add(..)
的引用,它记住了x
是1
。我们称这个函数引用为plusOne(..)
。 - 当我们调用
makeAdder(10)
时,我们得到了另一个指向它内部的add(..)
引用,它记住了x
是10
。我们称这个函数引用为plusTen(..)
。 - 当我们调用
plusOne(3)
时,它在3
(它内部的y
)上加1
(被x
记住的),于是我们得到结果4
。 - 当我们调用
plusTen(13)
时,它在13
(它内部的y
)上加10
(被x
记住的),于是我们得到结果23
。
如果这看起来很奇怪和令人困惑,不要担心 —— 它确实是的!要完全理解它需要很多的练习。
但是相信我,一旦你理解了它,它就是编程中最强大最有用的技术之一。让你的大脑在闭包中煎熬一会是绝对值得的。在下一节中,我们将进一步实践闭包。
11.原型
JavaScript中的原型机制十分复杂。我们在这里仅仅扫它一眼。要了解关于它的所有细节,你需要花相当的时间来学习本系列的 this与对象原型 的第四到六章。
当你引用一个对象上的属性时,如果这个属性不存在,JavaScript将会自动地使用这个对象的内部原型引用来寻找另外一个对象,在它上面查询你想要的属性。你可以认为它几乎是在属性缺失时的备用对象。
从一个对象到它备用对象的内部原型引用链接发生在这个对象被创建的时候。说明它的最简单的方法是使用称为Object.create(..)
的内建工具。
考虑如下代码:
var foo =
a: 42
;
// 创建 `bar` 并将它链接到 `foo`
var bar = Object.create( foo );
bar.b = "hello world";
bar.b; // "hello world"
bar.a; // 42 <-- 委托到 `foo`
将对象foo
和bar
以及它们的关系可视化也许会有所帮助:
属性a
实际上不存在于对象bar
上,但是因为bar
被原型链接到foo
,JavaScript自动地退到对象foo
上去寻找a
,而且在这里找到了它。
这种链接看起来是语言的一种奇怪的特性。这种特性最常被使用的方式 —— 我会争辩说这是一种滥用 —— 是用来模拟/模仿“类”机制的“继承”。
使用原型的更自然的方式是一种称为“行为委托”的模式,在这种模式中你有意地将你的被链接的对象设计为可以从一个委托到另一个的部分所需的行为中。
注意: 更多关于原型和行为委托的信息,参见本系列的 this与对象原型 的第四到六章。
12.参考内容
其他部分的详细介绍可参考以下网站。
以上是关于JavaScript学习的主要内容,如果未能解决你的问题,请参考以下文章