[JavaScript]一:概念/特色/语法/函数/数组

news/2024/7/19 16:30:18 标签: js, javascript, 编程语言

---- 本系列仅为个人学习总结,基于阮一峰大佬的《>>JavaScript 教程<<》---

目录

 一.概念

一些特点总结

二.使用范围 

(1)浏览器的平台化

(2)Node

(3)数据库操作

(4)移动平台开发

(5)内嵌脚本语言

(6)跨平台的桌面应用程序

著名程序员 Jeff Atwood 甚至提出了一条 “Atwood 定律”:

三.>>JavaScript 与 Java 的关系<< 

四.基本语法

1.变量

JavaScript 保留关键字 :

 2.注释

3.区块

4.if()   if...else语句  switch语句 while语句 for语句(与C语言语法基本相同)

等值比较优先使用===,!==   而非 ==   !=  

三元运算符

标签(相当于定位符)

五.数据类型

undefined典型场景

布尔值

对象

链式引用

对象的引用

with()

函数

函数声明

>>函数名的提升<<

name属性

length 属性(定义时的参数个数)

函数本身的作用域

易错点:

闭包

>>立即调用的函数表达式(IIFE)<<

作用:

好处:

 数组

>>类似数组的对象<<



 一.概念

JavaScript 是一种轻量级的脚本语言。所谓“脚本语言”(script language),指的是它不具备开发操作系统的能力,而是只用来编写控制其他大型应用程序(比如浏览器)的“脚本”。

JavaScript 也是一种嵌入式(embedded)语言。它本身提供的核心语法不算很多,只能用来做一些数学和逻辑运算。JavaScript 本身不提供任何与 I/O(输入/输出)相关的 API,都要靠宿主环境(host)提供,所以 JavaScript 只合适嵌入更大型的应用程序环境,去调用宿主环境提供的底层 API。

以浏览器为例,它提供的额外 API 可以分成三大类。

  • 浏览器控制类:操作浏览器
  • DOM 类:操作网页的各种元素
  • Web 类:实现互联网的各种功能

如果宿主环境是服务器,则会提供各种操作系统的 API,比如文件操作 API、网络通信 API等等。这些你都可以在 Node 环境中找到。

一些特点总结

  •  JavaScript 语言本身,虽然是一种解释型语言,但是在现代浏览器中,JavaScript 都是编译后运行。
  • 既支持类似 C 语言清晰的过程式编程,也支持灵活的函数式编程,可以用来写并发处理(concurrent)。这些语法特性已经被证明非常强大,可以用于许多场合,尤其适用异步编程。JavaScript 的编程风格是函数式编程和面向对象编程的一种混合体
  • JavaScript 的所有值都是对象,这为程序员提供了灵活性和便利性。因为你可以很方便地、按照需要随时创造数据结构,不用进行麻烦的预定义。
  • 可以采用事件驱动(event-driven)和非阻塞式(non-blocking)设计,在服务器端适合高并发环境,普通的硬件就可以承受很大的访问量。
  • 开放性,它的标准 ECMA-262 是 ISO 国际标准,写得非常详尽明确;该标准的主要实现(比如 V8 和 SpiderMonkey 引擎)都是开放的,而且质量很高。这保证了这门语言不属于任何公司或个人,不存在版权和专利的问题。
  • 原始设计目标是一种小型的、简单的动态语言,与 Java 有足够的相似性,使得使用者(尤其是 Java 程序员)可以快速上手。

二.使用范围 

(1)浏览器的平台化

随着 HTML5 的出现,浏览器不再仅仅能浏览网页,而是越来越像一个平台,JavaScript 因此得以调用许多系统功能,比如操作本地文件、操作图片、调用摄像头和麦克风等等。

(2)Node

Node 项目使得 JavaScript 可以用于开发服务器端的大型项目,网站的前后端都用 JavaScript 开发已经成为了现实,有些嵌入式平台(Raspberry Pi)能够安装 Node

(3)数据库操作

NoSQL 数据库这个概念,本身就是在 JSON(JavaScript Object Notation)格式的基础上诞生的,大部分 NoSQL 数据库允许 JavaScript 直接操作。

(4)移动平台开发

一般来说,安卓平台使用 Java 语言开发,iOS 平台使用 Objective-C 或 Swift 语言开发。许多人正在努力,让 JavaScript 成为各个平台的通用开发语言。

(5)内嵌脚本语言

越来越多的应用程序,将 JavaScript 作为内嵌的脚本语言,比如 Adobe 公司的著名 PDF 阅读器 Acrobat、Linux 桌面环境 GNOME 3。

(6)跨平台的桌面应用程序

Chromium OS、Windows 8 等操作系统直接支持 JavaScript 编写应用程序。Mozilla 的 Open Web Apps 项目、Google 的 Chrome App 项目、GitHub 的 Electron 项目、以及 TideSDK 项目,都可以用来编写运行于 Windows、Mac OS 和 Android 等多个桌面平台的程序,不依赖浏览器。

著名程序员 Jeff Atwood 甚至提出了一条 “Atwood 定律”:

“所有可以用 JavaScript 编写的程序,最终都会出现 JavaScript 的版本。”(Any application that can be written in JavaScript will eventually be written in JavaScript.)

三.>>JavaScript 与 Java 的关系<< 

四.基本语法

1.变量

  1. 如果变量赋值的时候,忘了写var命令,这条语句也是有效的, 但不利于表达意图,而且容易不知不觉地创建全局变量,所以建议总是使用var命令声明变量。
  2. 一个变量没有声明就直接使用,JavaScript 会报错,告诉你变量未定义。
  3. JavaScript 是一种动态类型语言,也就是说,变量的类型没有限制,变量可以随时更改类型。
  4. 使用var重新声明一个已经存在的变量,是无效的, 但是,如果第二次声明的时候还进行了赋值,则会覆盖掉前面的值
javascript">var a = 1;
// 基本等同
a = 1;


x
// ReferenceError: x is not defined


var a = 1;
a = 'hello';


var x = 1;
var x;//无效
x // 1

          5.变量提升:JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行, 这造成所有变量的声明语句都会被提升到代码的头部

javascript">console.log(a);
var a = 1;
//等同于👇👇👇,不会报错

var a;
console.log(a);
a = 1;

>>undefined //表示变量a已声明,但还未赋值

标识符(最常见的为变量)命名规则

  • 第一个字符,可以是任意 Unicode 字母(包括英文字母和其他语言的字母),以及美元符号($)和下划线(_)。
  • 第二个字符及后面的字符,除了 Unicode 字母、美元符号和下划线,还可以用数字0-9

javascript">//合法的标识符

arg0
_tmp
$elem
π
//不合法的标识符

1a  // 第一个字符不能是数字
23  // 同上
***  // 标识符不能包含星号
a+b  // 标识符不能包含加号
-d  // 标识符不能包含减号或连词线

中文是合法的标识符,可以用作变量名。 

var 临时变量 = 1;

JavaScript 保留关键字 :

(不可以用作变量、标签或者函数名。有些保留关键字是作为 Javascript 以后扩展使用)

abstractargumentsbooleanbreakbyte
casecatchcharclass*const
continuedebuggerdefaultdeletedo
doubleelseenum*evalexport*
extends*falsefinalfinallyfloat
forfunctiongotoifimplements
import*ininstanceofintinterface
letlongnativenewnull
packageprivateprotectedpublicreturn
shortstaticsuper*switchsynchronized
thisthrowthrowstransienttrue
trytypeofvarvoidvolatile
whilewithyield

* 标记的关键字是 ECMAScript5 中新添加的。

 2.注释

//略略略

/*
    略略略
*/


兼容HTML的注释
<!-- 略略略 -->

3.区块

{
  var a = 1;
}

a // 1
//在区块内部,使用var命令声明并赋值了变量a,然后在区块外部,变量a依然有效
//区块对于var命令不构成单独的作用域
//往往用来构成其他更复杂的语法结构,比如for、if、while、function等。

4.if()   if...else语句  switch语句 while语句 for语句(与C语言语法基本相同)

等值比较优先使用===,!==   而非 ==   !=  

(这意味着比较时不会发生类型转换。)

补充:switch语句部分和case语句部分,都可以使用表达式。 

javascript">switch (1 + 3) {
  case 2 + 2:
    f();
    break;
  default:
    other();
}

三元运算符

javascript">
(条件) ? 表达式1 : 表达式2

//利用三元运算符,输出相应的提示。
var m;
console.log(
  m ?
  'm is a boy' :
  'm is a girl'
)

>>m is a girl


//利用三元运算符,可以在字符串之中插入不同的值。
var msg = '数字' + n + '是' + (n % 2 === 0 ? '偶数' : '奇数');

标签(相当于定位符)

(搭配break continue跳出特定的循环)

芜湖,这样就可以干脆利落地跳出或者重新执行双重循环咯!!!

如果break/continue语句后面不使用标签,则只能进入下一轮的内层循环。

javascript">
actionA:
  for (..; ...; ...){
    for (...; ...; ...){
      if (...) break actionA;
      f();
    }
  }


actionB:
  for (..; ...; ...){
    for (...; ...; ...){
      if (...) continue actionB;
      f();
    }
  }

也可以用于跳出代码块

javascript">block: {
  console.log(1);
  break block;
  console.log('本行不会输出');
}
console.log(2);

// 1
// 2

五.数据类型

详见MDN>>JavaScript 数据类型和数据结构<<

JavaScript 有三种方法,可以确定一个值到底是什么类型。

  • typeof运算符
  • instanceof运算符
  • Object.prototype.toString方法

最新的 ECMAScript 标准定义了 8 种数据类型:

   1. 6 种原始类型,使用 typeof 运算符检查:

  •         undefined
  •         Boolean
  •         Number
  •         String
  •         BigInt
  •         Symbol 

    2.null

    3.Object

任何 constructed 对象实例的特殊非数据结构类型,也用做数据结构:new Object,new Array,new Map,new Set,new WeakMap,new WeakSet,new Date,和几乎所有通过 new keyword 创建的东西。

记住 typeof 操作符的唯一目的就是检查数据类型,如果我们希望检查任何从 Object 派生出来的结构类型,使用 typeof 是不起作用的,因为总是会得到 "object"。检查 Object 种类的合适方式是使用 instanceof 关键字。但即使这样也存在误差。

javascript">typeof 123      // "number"
typeof '123'    // "string"
typeof false    // "boolean"

function f() {}
typeof f        // "function"

typeof undefined// "undefined"

v    // ReferenceError: v is not defined
typeof v        // "undefined"

如果变量v没有用var命令声明,直接使用就会报错。但是,放在typeof后面,就不报错了,而是返回undefined,实际编程中,这个特点通常用在判断语句

javascript">// 错误的写法
if (v) {
  // ...
}
// ReferenceError: v is not defined

// 正确的写法
if (typeof v === "undefined") {
  // ...
}

undefined典型场景

javascript">一.变量声明了,但没有赋值
var i;
i // undefined

二.调用函数时,应该提供的参数没有提供,该参数等于 undefined
function f(x) {
  return x;
}
f() // undefined

三.对象没有赋值的属性
var  o = new Object();
o.p // undefined

四.函数没有返回值时,默认返回 undefined
function f() {}
f() // undefined

布尔值

如果 JavaScript 预期某个位置应该是布尔值,会将该位置上现有的值自动转为布尔值。转换规则是除了下面六个值被转为false,其他值都视为true

  • undefined
  • null
  • false
  • 0
  • NaN
  • ""''(空字符串)
javascript">if ('') {
    console.log('none-empty');
}else{
    console.log('empty');
}

// empty

注意,空数组([])和空对象({})对应的布尔值,都是true 

javascript">if ([]) {
  console.log('true');
}
// true

if ({}) {
  console.log('true');
}
// true

对象

属性可以动态创建,不必在对象声明时就指定。

链式引用

javascript">var o1 = {};
var o2 = { 
    option: f(x) {
        return x+100;
    } 
};

o1.foo = o2;
o1.foo.option(55) // 155

对象的引用

javascript">var o1 = {};
var o2 = o1;

o1.a = 1;
o2.b = 2;

o1.b // 2
o2.a // 1

o1和o2指向同一个对象,因此为其中任何一个变量添加属性,另一个变量都可以读写该属性。

此时,如果取消某一个变量对于原对象的引用,不会影响到另一个变量。

var o1 = {};
var o2 = o1;

o1 = 1;
o2 // {}

o1和o2指向同一个对象,然后o1的值变为1,这时不会对o2产生影响,o2还是指向原来的那个对象。

但是,这种引用只局限于对象,如果两个变量指向同一个原始类型的值。那么,变量这时都是值的拷贝。
如:
var x = 1;
var y = x;

x = 2;
y // 1
y和x并不是指向同一个内存地址。

查看一个对象本身的所有属性,可以使用Object.keys方法。

javascript">var obj = {
  key1: 1,
  key2: 2
};

Object.keys(obj);
// ['key1', 'key2']

delete命令用于删除对象的属性,删除成功后返回true。删除一个不存在的属性,delete不报错,而且返回true

javascript">var obj = { p: 1 };
Object.keys(obj) // ["p"]

delete obj.p // true
obj.p // undefined
Object.keys(obj) // []


var obj2 = {};
delete obj2.p // true

该属性存在,且不得删除时 , delete命令会返回false 

delete命令只能删除对象本身的属性,无法删除继承的属性

javascript">var obj = Object.defineProperty({}, 'p', {
  value: 123,
  configurable: false
});

obj.p // 123
delete obj.p // false

//toString是对象obj继承的属性,虽然delete命令返回true,
//但该属性并没有被删除,依然存在。这个例子还说明,
//即使delete返回true,该属性依然可能读取到值
delete obj.toString // true
obj.toString // function toString() { [native code] }

for...in循环用来遍历一个对象的全部属性(会跳过不可遍历的属性)

javascript">var obj = {a: 1, b: 2, c: 3};

for (var i in obj) {
  console.log('键名:', i);
  console.log('键值:', obj[i]);
}
// 键名: a
// 键值: 1
// 键名: b
// 键值: 2
// 键名: c
// 键值: 3

with()

javascript">var obj = {
  p1: 1,
  p2: 2,
};
with (obj) {
  p1 = 4;
  p2 = 5;
}
// 等同于
obj.p1 = 4;
obj.p2 = 5;

注意,如果with区块内部有变量的赋值操作,必须是当前对象已经存在的属性,否则会创造一个当前作用域的全局变量。

javascript">var obj = {};
with (obj) {
  p1 = 4;
  p2 = 5;
}

obj.p1 // undefined
p1 // 4

with语句的一个很大的弊病,就是绑定对象不明确。
单纯从代码块根本无法判断是全局变量,还是对象obj的一个属性

javascript">with (obj) {
  console.log(x);
}


因此,建议不要使用with语句,可以考虑用一个临时变量代替with。

javascript">with(obj1.obj2.obj3) {
  console.log(p1 + p2);
}

// 可以写成
var temp = obj1.obj2.obj3;
console.log(temp.p1 + temp.p2);

函数

函数声明

  • 函数的表达式需要在语句的结尾加上分号,表示语句结束。而函数的声明在结尾的大括号后面不用加分号
  • 如果同一个函数被多次声明,后面的声明就会覆盖前面的声明

(1)function 命令

javascript">function print(s) {
  console.log(s);
}

(2)函数表达式

javascript">var print = function(s) {
  console.log(s);
};

采用函数表达式声明函数时,function命令后面不带有函数名。如果加上函数名,该函数名只在函数体内部有效,在函数体外部无效。

javascript">var print = function x(){
  console.log(typeof x);
};

x
// ReferenceError: x is not defined

print()
// function

上面代码在函数表达式中,加入了函数名x。这个x只在函数体内部可用,指代函数表达式本身,其他地方都不可用。这种写法的用处有两个,一是可以在函数体内部调用自身,二是方便除错(除错工具显示函数调用栈时,将显示函数名,而不再显示这里是一个匿名函数)。因此,下面的形式声明函数也非常常见。

javascript">var f = function f() {};

 (3)Function 构造函数(非常不直观,几乎无人使用)

javascript">var add = new Function(
  'x',
  'y',
  'return x + y'
);

// 等同于
function add(x, y) {
  return x + y;
}

只有最后一个参数会被当做函数体,其他参数都是add函数的参数,
如果只有一个参数,该参数就是函数体。

var foo = new Function(
  'return "hello world";'
);

// 等同于
function foo() {
  return 'hello world';
}

>>函数名的提升<<

name属性

javascript">function f1() {}
f1.name // "f1"
----------
var f2 = function () {};
f2.name // "f2"
----------
var f3 = function myName() {};
f3.name // 'myName'

----------
name属性的一个用处,就是获取参数函数的名字, 从而知道传入的参数是什么函数。
var myFunc = function () {};

function test(f) {
  console.log(f.name);
}

test(myFunc) // myFunc

length 属性(定义时的参数个数)

javascript">function f(a, b) {}
f.length // 2

length属性提供了一种机制,判断定义时和调用时参数的差异,以便实现面向对象编程的“方法重载”(overload)。

函数本身的作用域

函数执行时所在的作用域,是定义时的作用域,而不是调用时所在的作用域。

javascript">var a = 1;
var x = function () {
  console.log(a);
};

function f() {
  var a = 2;
  x();
}

f() // 1

x是在函数f的外部声明的,所以它的作用域绑定外层,
内部变量a不会到函数f体内取值,所以输出1,而不是2

易错点:

如果函数A调用函数B,却没考虑到函数B不会引用函数A的内部变量。

javascript">var x = function () {
  console.log(a);
};

function y(f) {
  var a = 2;
  f();
}

y(x)
// ReferenceError: a is not defined

闭包

即能够读取其他函数内部变量的函数.

示例:

function f1() {
  var n = 999;
  function f2() {
    console.log(n);
  }
  return f2;
}

var result = f1();
result(); // 999

在 JavaScript 语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。闭包最大的特点,就是它可以“记住”诞生的环境,比如f2记住了它诞生的环境f1,所以从子函数f2可以得到f1的内部变量。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

闭包用处:

  • 读取外层函数内部的变量
  • 让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在,闭包使得内部变量记住上一次调用时的运算结果(类似C++中的类)
  • 封装对象的私有属性和私有方法 
javascript">function createIncrementor(start) {
  return function () {
    return start++;
  };
}

var inc = createIncrementor(5);

inc() // 5
inc() // 6
inc() // 7

start是函数createIncrementor的内部变量, 通过闭包,start的状态被保留

那为什么闭包能够返回外层函数的内部变量?原因是闭包(上例的inc)用到了外层变量(start),导致外层函数(createIncrementor)不能从内存释放。只要闭包没有被垃圾回收机制清除,外层函数提供的运行环境也不会被清除,它的内部变量就始终保存着当前值,供闭包读取。

所以闭包可以看作是函数内部作用域的一个接口

注意,外层函数每次运行,都会生成一个新的闭包,而这个闭包又会保留外层函数的内部变量,所以内存消耗很大。因此不能滥用闭包,否则会造成网页的性能问题。

>>立即调用的函数表达式(IIFE)<<

作用:

在定义函数之后,立即调用该函数

好处:

  1. 不必为函数命名,避免了污染全局变量;
  2.  IIFE 内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。

 数组

任何类型的数据,都可以放入数组 

javascript">var arr = [
  {a: 1},
  [1, 2, 3],
  function() {return true;}
];

arr[0] // Object {a: 1}
arr[1] // [1, 2, 3]
arr[2] // function (){return true;}

 如果数组的元素还是数组,就形成了多维数组

javascript">var a = [[1, 2], [3, 4]];
a[0][1] // 2
a[1][1] // 4

清空数组的一个有效方法,就是将length属性设为0

javascript">var arr = [ 'a', 'b', 'c' ];
arr.length // 3

arr.length = 2;
arr // ["a", "b"]
arr.length = 0;
arr // []

由于数组本质上是一种对象,所以可以为数组添加属性,但是这不影响length属性的值

javascript">将数组的键分别设为字符串和小数,结果都不影响length属性。

var a = [];

a['p'] = 'abc';
a.length // 0

a[2.1] = 'abc';
a.length // 0
因为length属性的值就是等于最大的数字键加1,
而这个数组没有整数键,所以length属性保持为0

>>类似数组的对象<<


http://www.niftyadmin.cn/n/816864.html

相关文章

[转载]JavaScript 的 this 原理

转自:JavaScript 的 this 原理 - 阮一峰的网络日志 (ruanyifeng.com) 目录 一、问题的由来 二、内存的数据结构 三、函数 四、环境变量 一、问题的由来 学懂 JavaScript 语言&#xff0c;一个标志就是理解下面两种写法&#xff0c;可能有不一样的结果。 var obj {foo: fu…

luogu P3267 [JLOI2016/SHOI2016] 侦查守卫

传送门 今天开始尽量补一补欠的70多道题的blog...(菜啊) 都是几句话的事 周末大概就完了 一看不是树dp经典题吗 最小覆盖 然后告诉我有些点不必覆盖? 20minutes later 发现其实是一样的...因为不必覆盖不是一定不能覆盖 其实是我一开始想成记录放的节点个数那个题 然后状态设计…

RabbitMQ c#版实现(转)

出处&#xff1a;https://www.cnblogs.com/hanfan/p/9842301.html 网上很多人已经总结的很好了&#xff0c;比如今天看到的这个。https://www.cnblogs.com/LipeiNet/p/9877189.html 我就不总结了&#xff0c;贴点代码。 RabbitMQConnect.cs 1234567891011121314151617181920212…

你我都在同一辆公交车上

10月31日&#xff0c;上海师范大学心理学教授李正云老师&#xff0c;给大家上了一堂可以说是职业教育课&#xff0c;印象最深的一点就是&#xff0c;永远不要被某一个学生打乱了课堂教学安排&#xff0c;课堂上&#xff0c;教师才是整个课堂的主导者&#xff0c;不能因为个别学…

Python学习笔记:import sys模块(argv、path、platform、exit)

sys模块是Python标准库中自带的一个模块。 sys模块包括了一组非常实用的服务&#xff0c;内含很多函数方法和变量&#xff0c;用来处理Python运行时配置以及资源&#xff0c;从而可以与当前程序之外的系统环境交互&#xff0c;如&#xff1a;Python解释器。 一、导入sys模块 im…

[JavaStript学习记录] 二.面向对象 (loading...)

---- 本系列仅为个人学习总结,基于阮一峰大佬的《>>JavaScript 教程<<》--- 目录 一.new 命令 作用: 执行构造函数&#xff0c;返回一个实例对象 若不使用new命令&#xff0c;直接调用构造函数会怎样? 补充: new命令简化的内部流程&#xff0c; new.targe…

[JavaStript学习记录] 对象的继承

---- 本系列仅为个人学习总结,基于阮一峰大佬的《>>JavaScript 教程<<》--- 目录 一.原型对象 prototypep属性 Constructor属性 二.instanceof 运算符 注意:instanceof只能用于对象&#xff0c;不适用原始类型的值 三.构造函数的继承 第一步: 第二步: 另…

[JavaStript学习记录] 对原型链的一些理解

回忆一下昨天的学习内容,梳理一些疑惑 先写了一个简单的构造函数 function A(){var num0; }var aanew A();查看该函数的实例 为什么实例对象没有prototype属性呢? 下面是经过查证后我的理解 发现 1.aa 是 A 的一个实例,但是不是一个函数&#xff0c;所以没有prototype; A是…