add file:04-JavaScript语法基础:数组
This commit is contained in:
parent
a82c697adb
commit
bd37502d8d
@ -3,13 +3,13 @@
|
||||
|
||||
## WebStorm的简单设置
|
||||
|
||||
#### 1、主题修改
|
||||
#### 1、主题修改:
|
||||
|
||||
可能大家会觉得软件的界面不太好看,我们可以换一下主题。选择菜单栏“File--settings--apperance--theme”,主题选择Darcula:
|
||||
|
||||
![](http://img.smyhvae.com/20180118_1600.png)
|
||||
|
||||
#### 2、导入第三方主题
|
||||
#### 2、导入第三方主题:
|
||||
|
||||
系统提供的两种主题可能都不太好看,我们可以进入网站<http://color-themes.com/>来获取第三方主题,这里推荐两个主题,大家二选一即可:
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
|
||||
|
||||
#### 3、代码字体修改
|
||||
#### 3、代码字体修改:
|
||||
|
||||
选择菜单栏“File--settings--Editor--Font”:
|
||||
|
||||
@ -43,18 +43,26 @@
|
||||
|
||||
|
||||
|
||||
#### 4、关闭更新
|
||||
#### 4、关闭更新:
|
||||
|
||||
如下图所示:
|
||||
|
||||
![](http://img.smyhvae.com/20180118_1646.png)
|
||||
|
||||
#### 5、快捷键习惯的修改
|
||||
#### 5、快捷键习惯的修改:
|
||||
|
||||
|
||||
|
||||
|
||||
#### 7、配置代码的自动提示
|
||||
#### 7、配置代码的自动提示:
|
||||
|
||||
|
||||
|
||||
#### 14、修改文件编码为UTF-8:
|
||||
|
||||
WebStorm 2017.3.3版本的默认编码方式是 GBK,我们还是统一设置为UTF-8吧,不要坑队友哦:
|
||||
|
||||
![](http://img.smyhvae.com/20180124_1856.png)
|
||||
|
||||
|
||||
### 新建一个空的项目
|
||||
@ -73,14 +81,14 @@
|
||||
|
||||
**步骤如下:**
|
||||
|
||||
新建一个空的项目:
|
||||
(1)新建一个空的项目:
|
||||
![](http://img.smyhvae.com/20180118_1720.png)
|
||||
|
||||
然后新建一个html文件:
|
||||
(2)然后新建一个html文件:
|
||||
|
||||
![](http://img.smyhvae.com/20180118_1602.png)
|
||||
|
||||
新建一个空的文件夹,命名为`css`:
|
||||
(3)新建一个空的文件夹,命名为`css`:
|
||||
|
||||
![](http://img.smyhvae.com/20180118_1725.png)
|
||||
|
||||
@ -88,7 +96,7 @@
|
||||
|
||||
![](http://img.smyhvae.com/20180118_1730.png)
|
||||
|
||||
最后新建一个images文件夹,用于存放土片。这样的话,一个基本的项目结构就搭建好了:
|
||||
(4)最后新建一个images文件夹,用于存放土片。这样的话,一个基本的项目结构就搭建好了:
|
||||
|
||||
![](http://img.smyhvae.com/20180118_1733.png)
|
||||
|
||||
@ -96,6 +104,12 @@
|
||||
|
||||
|
||||
|
||||
(5)如果要新建JS文件的话,操作如下:
|
||||
|
||||
![](http://img.smyhvae.com/20180124_1859.png)
|
||||
|
||||
|
||||
|
||||
## 使用技巧
|
||||
|
||||
|
||||
|
@ -14,6 +14,19 @@ Web前端有三层:
|
||||
|
||||
- JavaScript:从交互的角度,描述**行为**(提升用户体验)
|
||||
|
||||
|
||||
JavaScript是世界上用的最多的**脚本语言**。
|
||||
|
||||
补充:
|
||||
|
||||
- 编译执行:把代码编译成CPU认识的语言(文件),然后整体的执行。
|
||||
|
||||
|
||||
- **脚本语言:不需要编译**,直接在运行时**边解析边执行**的语言。
|
||||
|
||||
- 弱类型语言:简单定义一个变量,可以有多种数据类型。(var temp)
|
||||
|
||||
|
||||
### JavaScript历史背景介绍
|
||||
|
||||
布兰登 • 艾奇(Brendan Eich,1961年~),1995年在网景公司,发明的JavaScript。
|
||||
@ -75,6 +88,33 @@ ECMAScript在2015年6月,发布了ECMAScript 6版本,语言的能力更强
|
||||
|
||||
- JavaScript不用关心其他的一些事情(比如内存的释放、指针等),更关心自己的业务。
|
||||
|
||||
### 浏览器工作原理
|
||||
|
||||
|
||||
20180124_1700.png
|
||||
|
||||
1、User Interface 用户界面,我们所看到的浏览器
|
||||
|
||||
2、Browser engine 浏览器引擎,用来查询和操作渲染引擎
|
||||
|
||||
3、Rendering engine 用来显示请求的内容,负责解析HTML、CSS
|
||||
|
||||
4、Networking 网络,负责发送网络请求
|
||||
|
||||
5、JavaScript Interpreter(解析者) JavaScript解析器,负责执行JavaScript的代码
|
||||
|
||||
6、UI Backend UI后端,用来绘制类似组合框和弹出窗口
|
||||
|
||||
7、Data Persistence(持久化) 数据持久化,数据存储 cookie、HTML5中的sessionStorage
|
||||
|
||||
|
||||
|
||||
参考链接:<https://www.2cto.com/kf/201202/118111.html>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### JavaScript是前台语言
|
||||
|
||||
JavaScript是前台语言,而不是后台语言。
|
||||
@ -105,7 +145,9 @@ PS:JS机械重复性的劳动几乎为0,基本都是创造性的劳动。而
|
||||
|
||||
## 开始写第一行JavaScript代码
|
||||
|
||||
### 写JavaScript代码的位置
|
||||
### JavaScript代码的书写位置
|
||||
|
||||
(1)内嵌的方式:
|
||||
|
||||
页面中,我们可以在`<body>`标签里放入`<script type=”text/javascript”></script>`标签对儿,并在`<script>`里书写JavaScript程序:
|
||||
|
||||
@ -119,6 +161,13 @@ text表示纯文本,因为JavaScript也是一个纯文本的语言。
|
||||
|
||||
PS:在Sublime Text里,输入`<sc`后,按tab键,可以自动补齐。
|
||||
|
||||
(2)外链式:引入外部JavaScript文件(放到body标签里,可以和内嵌的js代码并列)
|
||||
|
||||
```
|
||||
<script src="tool.js"></script>
|
||||
```
|
||||
|
||||
|
||||
### alert语句
|
||||
|
||||
我们要学习的第一个语句,就是alert语句。
|
||||
@ -247,7 +296,7 @@ PS:在Sublime Text里,输入`<sc`后,按tab键,可以自动补齐。
|
||||
|
||||
### 用户输入:prompt()语句
|
||||
|
||||
`prompt()`就是专门用来弹出能够让用户输入的对话框。
|
||||
`prompt()`就是专门用来弹出能够让用户输入的对话框。用得少,测试的时候可能会用。
|
||||
|
||||
JS代码如下:
|
||||
|
||||
@ -271,9 +320,9 @@ JS代码如下:
|
||||
var a = prompt("请输入一个数字"); // 必须用一个变量,来接收用户输入的值
|
||||
```
|
||||
|
||||
## 直接量:数字和字符串
|
||||
## 字面量:数字和字符串
|
||||
|
||||
“直接量”即**常量**,也称为“字面量”。看见什么,它就是什么。
|
||||
“字面量”即**常量**,是固定值。看见什么,它就是什么。
|
||||
|
||||
简单的直接量有2种:数字、字符串。
|
||||
|
||||
@ -358,10 +407,34 @@ implements、import、int、interface、long、native、package、private、prot
|
||||
```
|
||||
|
||||
|
||||
我们来整理一下变量的命名规则:
|
||||
|
||||
驼峰命名规则:getElementById/matherAndFather/aaaOrBbbAndCcc
|
||||
|
||||
|
||||
1.变量命名必须以字母或是下标符号”_”或者”$”为开头。
|
||||
2.变量名长度不能超过255个字符。
|
||||
3.变量名中不允许使用空格,首个字不能为数字。
|
||||
4.不用使用脚本语言中保留的关键字及保留符号作为变量名。
|
||||
5.变量名区分大小写。(javascript是区分大小写的语言)
|
||||
6.汉语可以作为变量名。但是不建议使用,因为 low
|
||||
|
||||
|
||||
## 变量的类型
|
||||
|
||||
变量里面能够存储数字、字符串等。变量会自动的根据存储内容的类型不同,来决定自己的类型。
|
||||
|
||||
|
||||
- **简单数据类型(值类型)**:字符串 String、数字 Number、布尔 Boolean、未定义 undefined、空 null。
|
||||
|
||||
- **复杂数据类型(引用类型)**:Object、function、Array、Date、RegExp、Error...
|
||||
|
||||
|
||||
简单数据类型:参数赋值的时候,传数值
|
||||
|
||||
复杂数据类型:参数赋值的时候,传地址(修改的同一片内存空间)
|
||||
|
||||
|
||||
### 数值型:number
|
||||
|
||||
如果一个变量中,存放了数字,那么这个变量就是数值型的。
|
||||
@ -385,6 +458,54 @@ typeof 变量
|
||||
|
||||
**在JavaScript中,只要是数,就是数值型(number)的**。无论整浮、浮点数(即小数)、无论大小、无论正负,都是number类型的。
|
||||
|
||||
**数值范围:**
|
||||
|
||||
由于内存的限制,ECMAScript 并不能保存世界上所有的数值。
|
||||
- 最小值:Number.MIN_VALUE,这个值为: 5e-324
|
||||
|
||||
- 最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308
|
||||
|
||||
- 无穷大:Infinity
|
||||
|
||||
- 无穷小:-Infinity
|
||||
|
||||
|
||||
**NaN和isNaN()函数:**
|
||||
|
||||
(1)NaN:Not a Number,非数值。
|
||||
|
||||
```
|
||||
console.log(“abc”/18); //结果是NaN
|
||||
```
|
||||
|
||||
Undefined和任何数值计算为NaN。NaN 与任何值都不相等,包括 NaN 本身。
|
||||
|
||||
(2)isNaN() :任何不能被转换为数值的值都会导致这个函数返回 true。
|
||||
|
||||
|
||||
```
|
||||
isNaN(NaN);// true
|
||||
isNaN(“blue”); // true
|
||||
isNaN(123); // false
|
||||
|
||||
```
|
||||
|
||||
|
||||
### undefined和null
|
||||
|
||||
|
||||
null和undefined有最大的相似性。看看null == undefined的结果(true)也就更加能说明这点。
|
||||
|
||||
但是null ===undefined的结果(false)。不过相似归相似,还是有区别的,就是和数字运算时,10 + null结果为:10;10 + undefined结果为:NaN。
|
||||
|
||||
|
||||
- 任何数据类型和undefined运算都是NaN;
|
||||
|
||||
- 任何值和null运算,null可看做0运算。
|
||||
|
||||
|
||||
|
||||
|
||||
### 字符串型:string
|
||||
|
||||
现有如下代码:
|
||||
@ -644,6 +765,8 @@ typeof 变量
|
||||
10
|
||||
```
|
||||
|
||||
(3)带两个参数时,表示进制转换。
|
||||
|
||||
|
||||
### 字符串转为浮点数(小数):`parseFloat()`:
|
||||
|
||||
@ -652,7 +775,7 @@ typeof 变量
|
||||
|
||||
### 隐式转换
|
||||
|
||||
我们知道,`"2"+1`得到的结果其实是字符串,但是`"2"-1`得到的结果却是数值1。,这是因为计算机自动帮我们进行了“**隐式转换**”。
|
||||
我们知道,`"2"+1`得到的结果其实是字符串,但是`"2"-1`得到的结果却是数值1,这是因为计算机自动帮我们进行了“**隐式转换**”。
|
||||
|
||||
|
||||
也就是说,`-`、`*`、`/`、`%``这几个符号会自动进行隐式转换。例如:
|
||||
@ -671,6 +794,27 @@ typeof 变量
|
||||
虽然程序可以对`-`、`*`、`/`、`%``这几个符号自动进行“隐式转换”;但作为程序员,我们最好自己完成转换,方便程序的可读性。
|
||||
|
||||
|
||||
### 4.1 任何简单类型转换成String
|
||||
|
||||
(1)方法1:变量+“” 或者 变量+“abc”
|
||||
|
||||
(2)方法2:
|
||||
|
||||
```
|
||||
String(变量)
|
||||
```
|
||||
|
||||
(3)方法三:
|
||||
|
||||
```
|
||||
变量.toSting()
|
||||
```
|
||||
|
||||
注意:undefined和null无toString方法,所以它们不能用方法三。
|
||||
|
||||
Null和undefined无toString方法。
|
||||
|
||||
|
||||
|
||||
## 我的公众号
|
||||
|
@ -298,8 +298,8 @@ for循环举例:
|
||||
函数定义的语法:
|
||||
|
||||
```javascript
|
||||
function 函数名字(){
|
||||
|
||||
function sum(a, b){
|
||||
return a+b;
|
||||
}
|
||||
```
|
||||
|
||||
@ -313,6 +313,8 @@ for循环举例:
|
||||
|
||||
- 大括号里面,是这个函数的语句。
|
||||
|
||||
PS:方法写完之后,我们在方法的前面输入`/**`,然后回车,会发现,注释的格式会自动补齐。
|
||||
|
||||
|
||||
### 第二步:函数的调用
|
||||
|
613
03-JavaScript基础/04-JavaScript语法基础:数组.md
Normal file
613
03-JavaScript基础/04-JavaScript语法基础:数组.md
Normal file
@ -0,0 +1,613 @@
|
||||
|
||||
|
||||
> 本文最初发表于[博客园](https://www.cnblogs.com/smyhvae/p/8359654.html),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。
|
||||
|
||||
> 以下是正文。
|
||||
|
||||
|
||||
## 数组的定义
|
||||
|
||||
之前学习的数据类型,只能存储一个值(字符串为一个值)。如果我们想存储多个值,就可以使用数组。
|
||||
|
||||
### 数组的定义
|
||||
|
||||
(1)字面量定义。举例:
|
||||
|
||||
```
|
||||
var arr = [1,2,3];
|
||||
```
|
||||
|
||||
(2)对象定义(数组的构造函数)。格式:
|
||||
|
||||
```
|
||||
var arr = new Array(参数);
|
||||
```
|
||||
|
||||
参数位置是一个数值时,表示数组长度;多个数值时,表示数组中的元素。
|
||||
|
||||
### 数组的操作
|
||||
|
||||
1、求数组的长度:
|
||||
|
||||
```
|
||||
数组的长度 = 数组名.length;
|
||||
```
|
||||
|
||||
可以通过修改数组的长度来改变数组中元素的个数,如果改小了,数组将从后面删除元素。(伪数组arguments的长度可以修改,但是不能修改里面的元素,后面单独讲)
|
||||
|
||||
2、获取数组中的元素:
|
||||
|
||||
```
|
||||
数组中的指定元素 = 数组名[索引值];
|
||||
```
|
||||
|
||||
数组的索引代表的是数组中的元素在数组中的位置,从0开始。
|
||||
|
||||
如果索引值有误(比如元素没那么多),系统不报错,而是会给定值为undefined。
|
||||
|
||||
### 遍历数组(重要)
|
||||
|
||||
遍历数组即:获取并操作数组中的每一个元素。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr = ["生命壹号","许嵩","永不止步"];
|
||||
for(var i = 0;i<arr.length;i++){
|
||||
console.log(arr[i]); // arr[i]代表的是数组中的每一个元素i
|
||||
}
|
||||
|
||||
console.log(arr);
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
![](http://img.smyhvae.com/20180124_2008.png)
|
||||
|
||||
## 数组Array的常用方法
|
||||
|
||||
Array数组是属于**内置对象**,我们可以在下面的网站上查询各种方法。
|
||||
|
||||
- MDN(开发者网站):<https://developer.mozilla.org/zh-CN/>
|
||||
|
||||
Array有各种api接口(Application Programming Interface,应用程序编程接),下面分别介绍。
|
||||
|
||||
(1)判断是否为数组:instanceof
|
||||
|
||||
```javascript
|
||||
布尔类型值 = A instanceof B;
|
||||
```
|
||||
|
||||
解释:判断A是否为B类型(instanceof 是一个关键字)。
|
||||
|
||||
在数组里,这种方法已经用的不多了,因为有下面这种方法。
|
||||
|
||||
(2)判断是否为数组:isArray()
|
||||
|
||||
```javascript
|
||||
布尔类型值 = Array.isArray(被检测的值) ;
|
||||
```
|
||||
|
||||
PS:属于HTML5中新增的方法。
|
||||
|
||||
(3)转换数组:toString()
|
||||
|
||||
```javascript
|
||||
字符串 = 数组.toString();
|
||||
```
|
||||
|
||||
解释:把数组转换成字符串,每一项用`,`分割。
|
||||
|
||||
(4)返回数组本身:valueOf()
|
||||
|
||||
```javascript
|
||||
数组本身 = 数组.valueOf();
|
||||
```
|
||||
|
||||
这个方法的意义不大。因为我们指直接写数组对象的名字,就已经是数组本身了。
|
||||
|
||||
(5)将数组中的元素用符号连接成字符串:join()
|
||||
|
||||
```javascript
|
||||
字符串 = 数组.join(参数);
|
||||
```
|
||||
|
||||
参数决定用什么符号进行连接。如果不写参数,则和toString()的效果一致。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr = ["生命壹号","许嵩","棒棒哒"];
|
||||
|
||||
console.log(arr.join()); //无参数
|
||||
console.log(arr.join(" ")); //用空格进行连接
|
||||
console.log(arr.join("")); //用空字符串进行连接
|
||||
console.log(arr.join("&")); //用符号"&"进行连接
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
```
|
||||
生命壹号,许嵩,棒棒哒
|
||||
|
||||
生命壹号 许嵩 棒棒哒
|
||||
|
||||
生命壹号许嵩棒棒哒
|
||||
|
||||
生命壹号&许嵩&棒棒哒
|
||||
```
|
||||
|
||||
join方法有一定的实际用途:当我们需要把一堆字符串进行连接时,我们可以把他们转换成数组,然后调用数组的join()方法。这样做有个好处是:内存不会溢出。
|
||||
|
||||
|
||||
## 伪数组:arguments
|
||||
|
||||
arguments代表的是实参。有个讲究的地方是:arguments**只在函数中使用**。
|
||||
|
||||
(1)返回函数**实参**的个数:arguments.length
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
fn(2,4);
|
||||
fn(2,4,6);
|
||||
fn(2,4,6,8);
|
||||
|
||||
function fn(a,b) {
|
||||
console.log(arguments);
|
||||
console.log(fn.length); //获取形参的个数
|
||||
console.log(arguments.length); //获取实参的个数
|
||||
|
||||
console.log("----------------");
|
||||
}
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
![](http://img.smyhvae.com/20180125_2140.png)
|
||||
|
||||
(2)返回正在执行的函数:arguments.callee
|
||||
|
||||
在使用函数**递归**调用时,推荐使用arguments.callee代替函数名本身。
|
||||
|
||||
(3)之所以说arguments是伪数组,是因为:**arguments可以修改元素,但不能改变数组的长短**。举例:
|
||||
|
||||
```javascript
|
||||
fn(2,4);
|
||||
fn(2,4,6);
|
||||
fn(2,4,6,8);
|
||||
|
||||
function fn(a,b) {
|
||||
arguments[0] = 99; //将实参的第一个数改为99
|
||||
arguments.push(8); //此方法不通过,因为无法增加元素
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 数组的添加和删除
|
||||
|
||||
(1)push():在数组**最后面**插入项,返回数组的长度
|
||||
|
||||
```javascript
|
||||
数组改后的长度 = 数组.push(元素);
|
||||
```
|
||||
|
||||
(2)pop():取出数组中的**最后一个**元素,返回被删除的元素
|
||||
|
||||
```javascript
|
||||
被删除的元素 = 数组.pop();
|
||||
```
|
||||
|
||||
(3)unshift():在数组**最前面**插入项,返回数组的长度
|
||||
|
||||
数组改后的长度 = 数组.unshift(元素);
|
||||
|
||||
(4)shift():取出数组中的**第一个**元素,返回被删除的元素
|
||||
|
||||
```javascript
|
||||
被删除的元素 = 数组.shift();
|
||||
```
|
||||
|
||||
## 数组的反转和排序
|
||||
|
||||
(1)reverse():翻转数组(返回值是反转后的数组,而且**原数组也已经被反转了**)
|
||||
|
||||
```
|
||||
反转后的数组 = 数组.reverse();
|
||||
```
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr = ["a","b","c","d","e","f"];
|
||||
|
||||
console.log(arr); //反转前打印
|
||||
console.log(arr.reverse()); //反转
|
||||
console.log(arr); //反转后打印
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
![](http://img.smyhvae.com/20180125_2220.png)
|
||||
|
||||
注意:反转后,打印原来的数组发现,原来的数组已经被反转了。
|
||||
|
||||
(2)sort():给数组排序,返回排序后的数组(排序的规则看参数)
|
||||
|
||||
```
|
||||
从小到大排序后的数组 = 数组.sort(function(a,b){
|
||||
return a-b;
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
- 无参:按照数组元素的**首字符对应的Unicode编码值**,从小到大排列数组元素。
|
||||
|
||||
- 带参:必须为函数(回调函数:callback)。这个回调函数中带有两个参数,代表数组中的前后元素。
|
||||
- 如果返回值(a-b)为负数,a排b前面。
|
||||
- 如果返回值(a-b)等于0,不动。
|
||||
- 如果返回值(a-b)为正数,a排b后面。
|
||||
|
||||
上面的这个带参的排序,其实是调用了底层的**冒泡排序**,小的排前面,大的排后面。
|
||||
|
||||
PS:sort方法的功能非常强大,能对数字和字母进行排列。
|
||||
|
||||
## 数组的一些其他方法
|
||||
|
||||
(1)concat() :把参数拼接到当前数组(原数组不会被修改)
|
||||
|
||||
```javascript
|
||||
新数组 = 数组1.concat(数组2);
|
||||
|
||||
```
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr1 = [1,2,3];
|
||||
var arr2 = ["a","b","c","d","e","f"];
|
||||
|
||||
console.log(arr1.concat(arr2)); //把参数拼接到当前数组
|
||||
console.log(arr1);
|
||||
console.log(arr2);
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
![](http://img.smyhvae.com/20180126_1040.png)
|
||||
|
||||
从打印结果中可以看到,原数组(数组1、数组2)并没有被修改。
|
||||
|
||||
(2)slice():从当前数组中截取一个新的数组(不影响原来的数组)
|
||||
|
||||
```javascript
|
||||
新数组 = 原数组.slice(开始位置index,结束位置index); //注意:索引值包括左边的,不包括右边的
|
||||
```
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr = ["a","b","c","d","e","f"];
|
||||
|
||||
console.log(arr.slice(2)); //从第二个值开始截取
|
||||
console.log(arr.slice(2,4)); //截取从第二个到第四个之间的值(不包括第四个值)
|
||||
console.log(arr.slice(-2)); //截取最后两个值
|
||||
console.log(arr.slice(4,2)); //空
|
||||
|
||||
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
![](http://img.smyhvae.com/20180126_1053.png)
|
||||
|
||||
(3)splice():删除当前数组的某些元素(原数组会被改变)
|
||||
|
||||
```javascript
|
||||
新数组 = 数组1.splice(起始索引index,需要操作的个数,弥补的值);
|
||||
```
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr11 = ["a","b","c","d","e","f"];
|
||||
var arr12 = arr11.splice(1); //从第一个位置开始,删除元素
|
||||
console.log("原数组:"+arr11);
|
||||
console.log("新数组:"+arr12);
|
||||
console.log("-----------");
|
||||
|
||||
var arr21 = ["a","b","c","d","e","f"];
|
||||
var arr22 = arr21.splice(1,3); //从第一个元素开始删除,一共删除3个元素
|
||||
console.log(arr21);
|
||||
console.log(arr22);
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
![](http://img.smyhvae.com/20180126_1113.png)
|
||||
|
||||
PS:第三个参数很少用,这里先不讲。
|
||||
|
||||
(3)获取数据的索引:indexOf()、lastIndexOf()
|
||||
|
||||
- indexOf():从前往后索引
|
||||
|
||||
- lastIndexOf() :从后往前索引
|
||||
|
||||
```javascript
|
||||
索引值 = 数组.indexOf/lastIndexOf(数组中的元素内容);
|
||||
```
|
||||
|
||||
PS:如果没找到返回-1。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr = ["a","b","c","d","e","d","c"];
|
||||
|
||||
console.log(arr.indexOf("c")); //从前往后,找"c"在哪个位置
|
||||
console.log(arr.lastIndexOf("d")); //从前往后,找"d"在哪个位置
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
![](http://img.smyhvae.com/20180126_1125.png)
|
||||
|
||||
## 数组迭代方法
|
||||
|
||||
数组迭代方法包括:every()、filter()、forEach()、map()、some()
|
||||
|
||||
PS:这几个方法**不会修改原数组**。
|
||||
|
||||
语法格式:
|
||||
|
||||
```
|
||||
数组/boolean/无 = 数组.every/filter/forEach/map/some(
|
||||
function(element,index,arr){
|
||||
程序和返回值;
|
||||
```
|
||||
|
||||
有了这几种方法,就可以替代一些for循环了。下面依次来介绍。
|
||||
|
||||
### every()方法
|
||||
|
||||
解释:对数组中每一项运行回调函数,如果都返回true,every就返回true;如果有一项返回false,则停止遍历,此方法返回false。
|
||||
|
||||
注意:every()方法的返回值是boolean值,参数是回调函数。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr1 = ["千古", "宿敌", "南山忆", "素颜"];
|
||||
var bool1 = arr1.every(function (element, index, array) {
|
||||
if (element.length > 2) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
console.log(bool1); //输出结果:false。只要有一个元素的长度是超过两个字符的,就返回false
|
||||
|
||||
var arr2 = ["千古", "宿敌", "南山", "素颜"];
|
||||
var bool2 = arr2.every(function (element, index, array) {
|
||||
if (element.length > 2) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
console.log(bool2); //输出结果:true。因为每个元素的长度都是两个字符。
|
||||
```
|
||||
|
||||
### some()方法
|
||||
|
||||
解释:对数组中每一项运行回调函数,只要有一项返回true,则停止遍历,此方法返回true。
|
||||
|
||||
### filter()方法
|
||||
|
||||
解释:对数组中每一项运行回调函数,该函数返回结果是true的项,将组成新的数组(返回值就是这个新的数组)。
|
||||
|
||||
```javascript
|
||||
var arr1 = ["千古", "宿敌", "南山忆", "素颜"];
|
||||
|
||||
var arr2 = arr1.filter(function (element, index, array) {
|
||||
if (element.length > 2) { //arr1中的元素,如果是长度超过2个字符的,我就把它放到arr2中去
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
console.log(arr1);
|
||||
console.log(arr2);
|
||||
|
||||
```
|
||||
|
||||
结果:
|
||||
|
||||
![](http://img.smyhvae.com/20180126_1410.png)
|
||||
|
||||
### forEach()方法
|
||||
|
||||
解释:遍历数组。
|
||||
|
||||
注意:无返回值,纯粹操作数组中的元素,所以应用场景并不多。
|
||||
|
||||
### map()方法
|
||||
|
||||
解释:对数组中每一项运行回调函数,返回该函数的结果,组成的新数组(返回值就是这个新的数组)。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr1 = ["千古", "宿敌", "南山忆", "素颜"];
|
||||
|
||||
var arr2 = arr1.map(function (element, index, array) {
|
||||
return element + "vae"; //给arr1中所有的元素增加字符串"vae",放到arr2中。
|
||||
});
|
||||
|
||||
console.log(arr1);
|
||||
console.log(arr2);
|
||||
```
|
||||
|
||||
结果:
|
||||
|
||||
![](http://img.smyhvae.com/20180126_1425.png)
|
||||
|
||||
## 清空数组
|
||||
|
||||
清空数组,有以下几种方式:
|
||||
|
||||
```javascript
|
||||
var array = [1,2,3,4,5,6];
|
||||
|
||||
array.splice(0); //方式1:删除数组中所有项目
|
||||
array.length = 0; //方式1:length属性可以赋值,在其它语言中length是只读
|
||||
array = []; //方式3:推荐
|
||||
```
|
||||
|
||||
## 数组练习
|
||||
|
||||
### 练习1
|
||||
|
||||
**问题**:将一个字符串数组输出为`|`分割的形式,比如“千古|宿敌|素颜”。使用两种方式实现。
|
||||
|
||||
答案:
|
||||
|
||||
方式1:(不推荐)
|
||||
|
||||
```javascript
|
||||
var arr = ["千古","宿敌","素颜"];
|
||||
var str = arr[0];
|
||||
var separator = "|";
|
||||
for(var i = 1;i< arr.length;i++) {
|
||||
str += separator+arr[i]; //从第1个数组元素开始,每个元素前面加上符号"|"
|
||||
}
|
||||
|
||||
console.log(str);
|
||||
```
|
||||
|
||||
输出结果:
|
||||
|
||||
![](http://img.smyhvae.com/20180126_1336.png)
|
||||
|
||||
不推荐这种方式,因为:由于字符串的不变性,str拼接过多的话,容易导致内存溢出(很多个str都堆放在栈里)。
|
||||
|
||||
方式2:(推荐。通过array数组自带的api来实现)
|
||||
|
||||
```javascript
|
||||
var arr = ["千古","宿敌","素颜"];
|
||||
|
||||
console.log(arr.join("|"));
|
||||
```
|
||||
|
||||
结果:
|
||||
|
||||
![](http://img.smyhvae.com/20180126_1339.png)
|
||||
|
||||
### 练习2
|
||||
|
||||
题目:将一个字符串数组的元素的顺序进行反转,使用两种种方式实现。提示:第i个和第length-i-1个进行交换。
|
||||
|
||||
答案:
|
||||
|
||||
方式1:
|
||||
|
||||
```javascript
|
||||
function reverse(array) {
|
||||
var newArr = [];
|
||||
for (var i = array.length - 1; i >= 0; i--) {
|
||||
newArr[newArr.length] = array[i];
|
||||
}
|
||||
return newArr;
|
||||
}
|
||||
```
|
||||
|
||||
方式2:(算法里比较常见的方式)
|
||||
|
||||
```javascript
|
||||
function reverse(array){
|
||||
for(var i=0;i<array.length/2;i++){
|
||||
var temp = array[i];
|
||||
array[i] = array[array.length-1-i];
|
||||
array[array.length-1-i] = temp;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
```
|
||||
|
||||
方式3:(数组自带的reverse方法)
|
||||
|
||||
现在我们学习了数组自带的api,我们就可以直接使用reverse()方法。
|
||||
|
||||
### 练习3
|
||||
|
||||
问题:针对工资的数组[1500,1200,2000,2100,1800],把工资超过2000的删除。
|
||||
|
||||
答案:
|
||||
|
||||
```javascript
|
||||
var arr1 = [1500, 1200, 2000, 2100, 1800];
|
||||
|
||||
var arr2 = arr1.filter(function (ele, index, array) {
|
||||
if (ele < 2000) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
console.log(arr1);
|
||||
console.log(arr2);
|
||||
```
|
||||
|
||||
结果:
|
||||
|
||||
![](http://img.smyhvae.com/20180126_1435.png)
|
||||
|
||||
### 练习4
|
||||
|
||||
问题:找到数组["c","a","z","a","x","a"]中每一个元素出现的次数。
|
||||
|
||||
分析:这道题建议用json数据来做,因为我们想知道a出现了几次,c出现了几次,x出现了几次。恰好`k:v .. k:v`这种键值对的形式就比数组方便很多了。
|
||||
|
||||
键值对的形式:用key代表数组中的元素,用value代表元素出现的次数。
|
||||
|
||||
略难,答案暂略。
|
||||
|
||||
### 练习5
|
||||
|
||||
问题:编写一个方法去掉一个数组中的重复元素。
|
||||
|
||||
分析:创建一个新数组,循环遍历,只要新数组中有老数组的值,就不用再添加了。
|
||||
|
||||
答案:
|
||||
|
||||
```javascript
|
||||
// 编写一个方法 去掉一个数组的重复元素
|
||||
var arr = [1,2,3,4,5,2,3,4];
|
||||
console.log(arr);
|
||||
var aaa = fn(arr);
|
||||
console.log(aaa);
|
||||
//思路:创建一个新数组,循环遍历,只要新数组中有老数组的值,就不用再添加了。
|
||||
function fn(array){
|
||||
var newArr = [];
|
||||
for(var i=0;i<array.length;i++){
|
||||
//开闭原则
|
||||
var bool = true;
|
||||
//每次都要判断新数组中是否有旧数组中的值。
|
||||
for(var j=0;j<newArr.length;j++){
|
||||
if(array[i] === newArr[j]){
|
||||
bool = false;
|
||||
}
|
||||
}
|
||||
if(bool){
|
||||
newArr[newArr.length] = array[i];
|
||||
}
|
||||
}
|
||||
return newArr;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 我的公众号
|
||||
|
||||
想学习<font color=#0000ff>**代码之外的软技能**</font>?不妨关注我的微信公众号:**生命团队**(id:`vitateam`)。
|
||||
|
||||
扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外:
|
||||
|
||||
![](http://img.smyhvae.com/2016040102.jpg)
|
226
03-JavaScript基础/05-JavaScript语法基础:函数.md
Normal file
226
03-JavaScript基础/05-JavaScript语法基础:函数.md
Normal file
@ -0,0 +1,226 @@
|
||||
|
||||
|
||||
|
||||
|
||||
## 函数
|
||||
|
||||
函数:就是将一些语句进行**封装**,然后通过**调用**的形式,执行这些语句。
|
||||
|
||||
**函数的作用:**
|
||||
|
||||
- 将大量重复的语句写在函数里,以后需要这些语句的时候,可以直接调用函数,避免重复劳动。
|
||||
|
||||
- 简化编程,让编程模块化。
|
||||
|
||||
先来看个例子:
|
||||
|
||||
```javascript
|
||||
console.log("你好");
|
||||
sayHello(); //调用函数
|
||||
//定义函数:
|
||||
function sayHello(){
|
||||
console.log("欢迎");
|
||||
console.log("welcome");
|
||||
}
|
||||
```
|
||||
|
||||
**1、第一步:函数的定义**
|
||||
|
||||
函数定义的语法:
|
||||
|
||||
```javascript
|
||||
function sum(a, b){
|
||||
return a+b;
|
||||
}
|
||||
```
|
||||
|
||||
解释如下:
|
||||
|
||||
- function:是一个关键字。中文是“函数”、“功能”。
|
||||
|
||||
- 函数名字:命名规定和变量的命名规定一样。只能是字母、数字、下划线、美元符号,不能以数字开头。
|
||||
|
||||
- 参数:后面有一对小括号,里面是放参数用的。
|
||||
|
||||
- 大括号里面,是这个函数的语句。
|
||||
|
||||
PS:方法写完之后,我们在方法的前面输入`/**`,然后回车,会发现,注释的格式会自动补齐。
|
||||
|
||||
|
||||
**2、第二步:函数的调用**
|
||||
|
||||
函数调用的语法:
|
||||
|
||||
```javascript
|
||||
函数名字();
|
||||
```
|
||||
|
||||
### 函数的参数:形参和实参
|
||||
|
||||
函数的参数包括形参和实参。来看下面的图就懂了:
|
||||
|
||||
|
||||
![](http://img.smyhvae.com/20180118_1130.png)
|
||||
|
||||
注意:实际参数和形式参数的个数,要相同。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
sum(3,4);
|
||||
sum("3",4);
|
||||
sum("Hello","World");
|
||||
|
||||
//函数:求和
|
||||
function sum(a, b) {
|
||||
console.log(a + b);
|
||||
}
|
||||
```
|
||||
|
||||
控制台输出结果:
|
||||
|
||||
```
|
||||
7
|
||||
34
|
||||
helloworld
|
||||
```
|
||||
|
||||
### 函数的返回值
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
console.log(sum(3, 4));
|
||||
//函数:求和
|
||||
function sum(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
```
|
||||
|
||||
return的作用是结束方法。
|
||||
|
||||
注意:
|
||||
|
||||
1. 如果函数没有显示的使用 return语句 ,那么函数有默认的返回值:undefined
|
||||
|
||||
2. 如果函数使用 return语句,那么跟再return后面的值,就成了函数的返回值
|
||||
|
||||
3. 如果函数使用 return语句,但是return后面没有任何值,那么函数的返回值 也是:undefined
|
||||
|
||||
4. 函数使用return语句后,这个函数会在执行完 return 语句之后停止并立即退 出,也就是说return后面的所有其他代码都不会再执行。
|
||||
|
||||
### 1.6 函数名、函数体和函数加载问题(重要,请记住)
|
||||
|
||||
我们要记住:**函数名 == 整个函数**。举例:
|
||||
|
||||
```javascript
|
||||
console.log(fn) == console.log(function fn(){alert(1)});
|
||||
|
||||
//定义fn方法
|
||||
function fn(){
|
||||
alert(1)
|
||||
};
|
||||
```
|
||||
|
||||
我们知道,当我们在调用一个函数时,通常使用`函数()`这种格式;但此时,我们是直接使用`函数`这种格式,它的作用相当于整个函数。
|
||||
|
||||
**函数的加载问题**:JS加载的时候,只加载函数名,不加载函数体。所以如果想使用内部的成员变量,需要调用函数。
|
||||
|
||||
|
||||
### 回调函数
|
||||
|
||||
我们知道,当函数自己调用自己时,称之为递归。本段来讲一下回调。
|
||||
|
||||
回调:**函数作为参数**,进行传递和使用,称之为**回调**。
|
||||
|
||||
举个最简单的例子:
|
||||
|
||||
```javascript
|
||||
fn(test); //回调test这个函数
|
||||
|
||||
function test() {
|
||||
console.log("我是被回调的函数")
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
输出结果:我是被回调的函数。
|
||||
|
||||
|
||||
**什么情况下使用回调函数:**
|
||||
|
||||
回调函数一般是用于**定义一个规则**。因为我们无法通过传递一个变量来传递规则。
|
||||
|
||||
换而言之:当我们需要**传递规则的时候,必须使用回调**。规则的传递只能通过函数来实现,无法通过变量实现。
|
||||
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
console.log(fn(12,3,test1)); //注意第三个参数是函数名
|
||||
console.log(fn(12,3,test2)); //注意第三个参数是函数名
|
||||
|
||||
//定义一个通用规则(包含加减乘数的抽象函数)
|
||||
fn(num1,num2,demo) {
|
||||
return demo(num1,num2);
|
||||
}
|
||||
|
||||
//定义四个规则:加减乘除
|
||||
function test1(a,b) {
|
||||
return a+b;
|
||||
}
|
||||
function test2(a,b) {
|
||||
return a-b;
|
||||
}
|
||||
function test3(a,b) {
|
||||
return a*b;
|
||||
}
|
||||
function test4(a,b) {
|
||||
return a/b;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
打印结果:
|
||||
|
||||
```
|
||||
15
|
||||
9
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
307
03-JavaScript基础/06-JavaScript语法基础:面向对象和内置对象.md
Normal file
307
03-JavaScript基础/06-JavaScript语法基础:面向对象和内置对象.md
Normal file
@ -0,0 +1,307 @@
|
||||
|
||||
|
||||
## 面向对象的概念
|
||||
|
||||
**对象的作用是:封装信息**。比如Student类里可以封装学生的姓名、年龄、成绩等。
|
||||
|
||||
那为什么不用数组封装信息呢?首先,数组只能存放同一种类型的数据;其次,要功过
|
||||
|
||||
对象具有**特征**(属性)和**行为**(方法)。
|
||||
|
||||
面向对象:可以创建自定义的类型、很好的支持继承和多态。
|
||||
|
||||
面向对象的特征:封装、继承、多态。
|
||||
|
||||
## 创建自定义对象
|
||||
|
||||
### 创建单个自定义对象
|
||||
|
||||
创建一个空白的对象,举例:
|
||||
|
||||
```
|
||||
var student= new Object();
|
||||
```
|
||||
|
||||
完整的举例如下:
|
||||
|
||||
```javascript
|
||||
//调用对象
|
||||
console.log(student); //调用对象的方法
|
||||
student.sayHi(); //调用对象的方法
|
||||
|
||||
|
||||
//(1)创建一个空白的对象
|
||||
var student= new Object();
|
||||
|
||||
// (2)定义对象的属性
|
||||
student.name = "生命壹号";
|
||||
student.age = 26;
|
||||
// (3)定义对象的方法
|
||||
student.sayHi = function () {
|
||||
console.log(this.name + "今年的岁数是" + this.age); //如果要调用自己的name,可以使用this
|
||||
}
|
||||
```
|
||||
|
||||
输出如下:
|
||||
|
||||
20180125_1059.png
|
||||
|
||||
### 引入:创建多个自定义对象
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var stu1 = createStudent("生命壹号");
|
||||
console.log(stu1);
|
||||
stu1.sayHi();
|
||||
|
||||
console.log("------------------");
|
||||
|
||||
var stu2 = createStudent("许嵩");
|
||||
console.log(stu2);
|
||||
stu2.sayHi();
|
||||
|
||||
|
||||
// 创建一个函数
|
||||
function createStudent(name) {
|
||||
var student = new Object();
|
||||
student.name = name; //第一个name指的是student对象定义的变量。第二个name指的是createStudent函数的参数。二者不一样
|
||||
student.sayHi = function () {
|
||||
console.log(this.name + "厉害了");
|
||||
}
|
||||
return student;
|
||||
}
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
20180125_1121.png
|
||||
|
||||
上方代码中,注意`student.name = name;`中这两个name是不同的。另外,注意this指的是student的this。
|
||||
|
||||
### new和this
|
||||
|
||||
**this:**
|
||||
|
||||
1、this只出现在函数中。
|
||||
|
||||
2、谁调用函数,this就指的是谁。
|
||||
|
||||
3、new People(); People中的this代指被创建的对象实例。
|
||||
|
||||
|
||||
**new之后:**
|
||||
|
||||
(1)开辟内存空间,存储新创建的对象。new Object()
|
||||
|
||||
(2)**把this设置为当前对象**
|
||||
|
||||
(3)执行内部代码,设置对象属性和方法
|
||||
|
||||
(4)返回新创建的对象
|
||||
|
||||
因为this指的是new一个Object之后的对象实例。于是,下面这段代码:
|
||||
|
||||
```javascript
|
||||
// 创建一个函数
|
||||
function createStudent(name) {
|
||||
var student = new Object();
|
||||
student.name = name; //第一个name指的是student对象定义的变量。第二个name指的是createStudent函数的参数。二者不一样
|
||||
}
|
||||
```
|
||||
|
||||
可以改进为:
|
||||
|
||||
```javascript
|
||||
// 创建一个函数
|
||||
function Student(name) {
|
||||
this.name = name; //this指的是构造函数中的对象实例
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
注意上方代码中的注释。
|
||||
|
||||
于是,便得出了接下来的代码。
|
||||
|
||||
**利用构造函数自定义对象:**(改进版)
|
||||
|
||||
```javascript
|
||||
//利用构造函数自定义对象
|
||||
var stu1 = new Student("smyh");
|
||||
console.log(stu1);
|
||||
stu1.sayHi();
|
||||
|
||||
var stu2 = new Student("vae");
|
||||
console.log(stu2);
|
||||
stu2.sayHi();
|
||||
|
||||
|
||||
// 创建一个构造函数
|
||||
function Student(name) {
|
||||
this.name = name; //this指的是构造函数中的对象实例
|
||||
this.sayHi = function () {
|
||||
console.log(this.name + "厉害了");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
20180125_1350.png
|
||||
|
||||
|
||||
|
||||
### 属性绑定
|
||||
|
||||
暂略。
|
||||
|
||||
|
||||
### 对象字面量
|
||||
|
||||
|
||||
**对象的字面量**就是一个{}。里面的属性和方法均是**键值对**。
|
||||
|
||||
例如:
|
||||
|
||||
```javascript
|
||||
var o = {
|
||||
name: "生命壹号",
|
||||
age: 26,
|
||||
isBoy: true,
|
||||
sayHi: function() {
|
||||
console.log(this.name);
|
||||
}
|
||||
};
|
||||
|
||||
console.log(o);
|
||||
```
|
||||
|
||||
控制台输出:
|
||||
|
||||
20180125_1834.png
|
||||
|
||||
**json的介绍:**
|
||||
|
||||
> 对象字面量和json比较像,这里我们对json做一个简单介绍。
|
||||
|
||||
JSON:JavaScript Object Notation(JavaScript对象表示形式)。
|
||||
|
||||
JSON和对象字面量的区别:JSON的属性必须用双引号引号引起来,对象字面量可以省略。
|
||||
|
||||
json举例:
|
||||
|
||||
```
|
||||
{
|
||||
"name" : "zs",
|
||||
"age" : 18,
|
||||
"sex" : true,
|
||||
"sayHi" : function() {
|
||||
console.log(this.name);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
注:json里一般放常量、数组、对象等,但很少放function。
|
||||
|
||||
另外,对象和json没有长度,json.length的打印结果是undefined。于是乎,自然也就不能用for循环遍历(因为便利时需要获取长度length)。
|
||||
|
||||
|
||||
|
||||
## 类和对象
|
||||
|
||||
函数并没有创建对象的能力,类才有。
|
||||
|
||||
|
||||
```javascript
|
||||
class Customer {
|
||||
//属性
|
||||
public String Name;
|
||||
public String Age;
|
||||
public String Money;
|
||||
|
||||
//方法
|
||||
public void Buy (String id,int num,double price) {
|
||||
self.money -= num * price; //记录订单
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
```javascript
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
```javascript
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
61
05-CSS进阶/02-JS的小知识.md
Normal file
61
05-CSS进阶/02-JS的小知识.md
Normal file
@ -0,0 +1,61 @@
|
||||
JS的小知识.md
|
||||
|
||||
|
||||
|
||||
|
||||
### 方法的注释
|
||||
|
||||
|
||||
方法写完之后,我们在方法的前面输入`/**`,然后回车,会发现,注释的格式会自动补齐。
|
||||
|
||||
|
||||
### 断点调试
|
||||
|
||||
(1)先让程序运行一遍。
|
||||
|
||||
(2)f12,弹出代码调试工具
|
||||
|
||||
(3)打断点:
|
||||
|
||||
![](http://img.smyhvae.com/20180124_2035.png)
|
||||
|
||||
然后刷新页面。
|
||||
|
||||
(4)一步步调试,每点击一次,执行一步:
|
||||
|
||||
![](http://img.smyhvae.com/20180124_2036.png)
|
||||
|
||||
(5)监视变量:
|
||||
|
||||
当然,也可以添加变量或者表达式到监视窗口。操作如下:
|
||||
|
||||
![](http://img.smyhvae.com/20180124_2037.png)
|
||||
|
||||
上图中,选择变量或表达式,然后右键add to watch.
|
||||
|
||||
然后监视窗口:
|
||||
|
||||
![](http://img.smyhvae.com/20180124_2038.png)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -34,7 +34,14 @@
|
||||
|
||||
- [02-JavaScript语法基础:运算符和表达式](./03-JavaScript/02-JavaScript语法基础:运算符和表达式.md)
|
||||
|
||||
- [03-JavaScript语法基础:if语句&for循环&函数](./03-JavaScript/03-JavaScript语法基础:if语句&for循环&函数.md)
|
||||
- [03-JavaScript语法基础:循环控制(if语句&for循环)](./03-JavaScript/03-JavaScript语法基础:循环控制(if语句&for循环).md)
|
||||
|
||||
- [04-JavaScript语法基础:数组](./03-JavaScript/04-JavaScript语法基础:数组.md)
|
||||
|
||||
- [05-JavaScript语法基础:函数](./03-JavaScript/05-JavaScript语法基础:函数.md)
|
||||
|
||||
- [06-JavaScript语法基础:面向对象和内置对象](./03-JavaScript/06-JavaScript语法基础:面向对象和内置对象.md)
|
||||
|
||||
|
||||
|
||||
## 前端基础练习
|
||||
|
21
推荐链接.md
21
推荐链接.md
@ -79,4 +79,25 @@
|
||||
|
||||
|
||||
|
||||
### 2018-01-24
|
||||
|
||||
推荐一个网站,名叫:web骇客。网址:<http://www.webhek.com/>
|
||||
|
||||
|
||||
比如:
|
||||
|
||||
|
||||
- 电影里敲代码的样子:<http://www.webhek.com/post/hackertyper.html>
|
||||
|
||||
- 测试眼睛对颜色的敏感程度:<http://www.webhek.com/post/color-test.html>
|
||||
|
||||
|
||||
|
||||
### 2018-01-25
|
||||
|
||||
- [面试分享:一年经验初探阿里巴巴前端社招](https://www.cnblogs.com/fsyz/p/8298921.html)
|
||||
|
||||
一般阿里社招都是招3-5年的P6+高级工程师。面试官明知道作者只有一年工作经验,在面了这么多轮之后却来一句:“我们只要高工”。这是不是太欺负人了?
|
||||
|
||||
|
||||
|
||||
|
167
面试相关/面经/20180116-博客园:一年经验初探阿里巴巴前端社招.md
Normal file
167
面试相关/面经/20180116-博客园:一年经验初探阿里巴巴前端社招.md
Normal file
@ -0,0 +1,167 @@
|
||||
|
||||
博客园:一年经验初探阿里巴巴前端社招
|
||||
|
||||
文章来源:<https://www.cnblogs.com/fsyz/p/8298921.html>
|
||||
|
||||
|
||||
一般阿里社招都是招3-5年的P6+高级工程师,当初自己一年经验也没有想过有这个面试机会。
|
||||
|
||||
虽然没想着换工作,但是经常关注一些招聘网站的信息,某一天,在某boss上有个人找我,叫我发一下简历,我一看是阿里的某技术专家,虽然之前也有阿里的在某boss上给我要简历,但是我深知自己经验不足,然后给boss说我是16届的,只有一年经验,然后就没有然后了。这次我依然这么回复,但是这boss说,没关系,他喜欢基础好的,让我可以试一试,于是我也抱着试一试的心态发了简历。
|
||||
|
||||
简历发过去之后,boss就给我打了电话,让我简单的介绍一下自己,我就噼里啪啦说了一些,还说了一些题外话。然后boss就开始问我问题。
|
||||
|
||||
由于面了四轮,所以最开始的面试记忆有点模糊了,细细回想,又感觉记忆犹新。
|
||||
|
||||
1.电话初探
|
||||
1.说一下你了解CSS盒模型。
|
||||
我就说了一下IE的怪异盒模型和标注浏览器的盒模型,然后可以通过box-sizing属性控制两种盒模型的变换。
|
||||
|
||||
2.说一下box-sizing的应用场景。
|
||||
这个也不难,简单说了一两个应用场景,具体就不一一细说了。
|
||||
|
||||
3.说一下你了解的弹性FLEX布局.
|
||||
这个我也比较了解,各种概念和属性能想到的说了一大堆,也扯到了Grid布局,基本这个也没啥问题。
|
||||
|
||||
4.说一下一个未知宽高元素怎么上下左右垂直居中。
|
||||
说了一下flex弹性布局的实现,说了一下兼容性,扯到了postcss的一些东西,然后说了一下常规的兼容性比较好的实现。
|
||||
|
||||
5.说一下原型链,对象,构造函数之间的一些联系。
|
||||
这个我之前写过相关的文章,自己也有比较深入的理解,所以这个也不在话下,噼里啪啦说了一大堆,也不知道面试官听得咋样。
|
||||
|
||||
6.DOM事件的绑定的几种方式
|
||||
说了三种,然后说了一些冒泡,默认事件,以及DOM2,DOM3级的一些标准。
|
||||
|
||||
7.说一下你项目中用到的技术栈,以及觉得得意和出色的点,以及让你头疼的点,怎么解决的。
|
||||
这个因人而异,开放性问题,主要考察平时项目的一些积累吧,这个我回答感觉也比较ok。
|
||||
|
||||
8.有没有了解http2.0,websocket,https,说一下你的理解以及你所了解的特性。
|
||||
这个我看过一些文章,但是没有什么印象,扯了一些概念,但是回答的不是很深。
|
||||
|
||||
第一轮电话初探,大约面了50分钟,就记起来这么多,还有一些细节问题可能淡忘了,总体来说,面的都是以基础为主,然后boss说把我简历推荐给内部,进行正式的社招流程。
|
||||
|
||||
一轮技术面
|
||||
然后当天晚上一个女的面试官就给我打电话了,说八点半进行下一轮技术面试,没想到效率这么快,我都没怎么准备。
|
||||
这次就直接省略自我介绍了。
|
||||
|
||||
1.webpack的入口文件怎么配置,多个入口怎么分割啥的,我也没太听清楚。
|
||||
这个自己就说了一下自己的理解,以及自己用node写的多入口怎么配置,然后面试官说不是多入口配置,然后我又说了一下自己的理解,然后这题就过了。
|
||||
|
||||
2.我看到你的项目用到了Babel的一个插件:transform-runtime以及stage-2,你说一下他们的作用。
|
||||
这个我也还算比较了解,就说了一下ES的一些API,比如generator啥的默认不转换,只转换语法,需要这个来转换,然后说profill啥的,扯了一下stage-1,stage-2,stage-3,这个问题回答还算清楚。
|
||||
|
||||
3.我看到你的webpack配置用到webpack.optimize.UglifyJsPlugin这个插件,有没有觉得压缩速度很慢,有什么办法提升速度。
|
||||
这个我主要回答了一下,我之前也没怎么了解,一个想到是缓存原理,压缩只重新压缩改变的,还有就是减少冗余的代码,压缩只用于生产阶段,然后面试官问还有呢?我就说,还可以从硬件上提升,可以得到质的飞跃,比如换台I9处理器的电脑。。。。
|
||||
|
||||
4.简历上看见你了解http协议。说一下200和304的理解和区别
|
||||
这个噼里啪啦说了一堆,协商缓存和强制缓存的区别,流程,还有一些细节,提到了expires,Cache-Control,If-none-match,Etag,last-Modified的匹配和特征,这一块之前有过比较详细的了解,所以还是应答如流。
|
||||
|
||||
5.DOM事件中target和currentTarget的区别
|
||||
这个没答上来。。。
|
||||
|
||||
6.说一下你平时怎么解决跨域的。以及后续JSONP的原理和实现以及cors怎么设置。
|
||||
我就说了一下Jason和cors,然后问我JSONP的原理以及cors怎么设置,这一块自己也实践过,所以还是对答如流的。
|
||||
|
||||
7.说一下深拷贝的实现原理。
|
||||
这个也还好,就是考虑的细节不是很周全,先是说了一种JSON.stringify和JSON.parse的实现,以及这种实现的缺点,主要就是非标准JSOn格式无法拷贝以及兼容性问题,然后问了我有么有用过IE8的一个什么JSON框架,我也不记得是什么了,因为我压根没听过,然后说了一下尾递归实现深拷贝的原理,还问了我typeof null是啥,这个当然是Object。。。
|
||||
|
||||
8.说一下项目中觉得可以改进的地方以及做的很优秀的地方?
|
||||
这个也是因人而异,开放性问题,大致扯了一下自己的经历,也还OK。
|
||||
|
||||
最后问了有什么需要问的地方,面试到这里基本就结束了,大约面了一个多钟头,还是蛮累的。总体来说,回答的广度和深度以及细节都还算OK,觉得这轮面试基本没什么悬念。
|
||||
|
||||
二轮技术面
|
||||
过了几天,接到阿里另一个面试官的电话,上一轮面试通过了,这次是二轮技术面,说估计一个钟头。这次依然跳过自我介绍之类的,直奔主题。
|
||||
|
||||
1.有没有自己写过webpack的loader,他的原理以及啥的,记得也不太清楚。
|
||||
这个我就说了一下,然后loader配置啥的,也还ok。
|
||||
|
||||
2.有没有去研究webpack的一些原理和机制,怎么实现的。
|
||||
这个我简单说了一下我自己了解的,因为这一块我也没深入去研究,所以说的应该比较浅。
|
||||
|
||||
3.babel把ES6转成ES5或者ES3之类的原理是什么,有没有去研究。
|
||||
这一块我说了一下自己的思路,大致也还OK,我也没去深入研究怎么转换的,之前好像看过类似的文章,自己也只观察过转换之后的代码是啥样的,至于怎么转换的规则,真的没去深入观察。
|
||||
|
||||
4.git大型项目的团队合作,以及持续集成啥的。
|
||||
这里我就说了一下自己了解的git flow方面的东西,因为没有实战经验,所以我就选择性说明了这一块的不熟练,然后面试官也没细问。
|
||||
|
||||
5.什么是函数柯里化?以及说一下JS的API有哪些应用到了函数柯里化的实现?
|
||||
这个我就说了一下函数柯里化一些了解,以及在函数式编程的应用,最后说了一下JS中bind函数和数组的reduce方法用到了函数柯里化。
|
||||
|
||||
6.ES6的箭头函数this问题,以及拓展运算符。
|
||||
这一块主要是API和概念的问题,扯了一些规范以及严格模式下其他情况this只想问题。
|
||||
|
||||
7.JS模块化Commonjs,UMD,CMD规范的了解,以及ES6的模块化跟其他几种的区别,以及出现的意义。
|
||||
这个也是说了一下自己的理解和认知,自己对模块化历史以及一些规范都有所涉猎,这一块也还凑合。
|
||||
|
||||
8.说一下Vue实现双向数据绑定的原理,以及vue.js和react.js异同点,如果让你选框架,你怎么怎么权衡这两个框架,分析一下。
|
||||
主要是发布订阅的设计模式,还有就是ES5的Object.defineProperty的getter和setter机制,然后顺便扯了一下Angular的脏检测,以及alvon.js最先用到这种方式。然后扯了一下vue.js和react.js异同点,权衡框架选择,调研分析之类,噼里啪啦说了一大堆。
|
||||
|
||||
9.我看你也写博客,说一下草稿的交互细节以及实现原理。
|
||||
这一款就按照自己用过简书或者掘金,SG这类草稿的体验,详细说了一下,这个开放性问题,说到点基本就OK。
|
||||
|
||||
最后面试官问我有什么想问的吗,面试到这里基本就结束了,差不多面了一个小时,说过几天就会给答复,如果过了就会去阿里园区进行下一轮的技术面。
|
||||
|
||||
三轮技术面
|
||||
上一轮发挥感觉没前两轮发挥好,所以还是有点不自信的,没想到第三天后,就来电话了,通知我去阿里园区面试。
|
||||
|
||||
因为阿里西溪园区距离我不到十公里,我就踩着共享单车一点钟就出发了,天气比较热,飘在路上,百感交集,身边一辆法拉利轰鸣而过,又一辆兰博基尼呼啸而过,我心里一万头草泥马奔腾,MLGB,心里暗想,为神马开这车的人不是此刻看文章的你?
|
||||
|
||||
走到半路了,面试官给我打电话了,说我怎么还没到,说约定的是两点钟,我一下子就懵逼了,短信只有一个游客访问ID,并没有通知我具体时间,反正不管谁的疏忽,我肯定是要迟到了,于是我快马加鞭,踩着贼难骑的共享单车,背着微风,一路狂奔,到阿里园区已是汗流浃背,油光满面,气喘乎乎。。。
|
||||
|
||||
面试迟到了,印象肯定不好,加上满头大汗的形象也不太好,加上自己饥渴难耐,这面是估计要GG了,一进来就直奔主题,这次是两个大Boss面试我。
|
||||
|
||||
第一个面试官
|
||||
1.先自我介绍一下,说一下项目的技术栈,以及项目中遇到的一些问题啥的。
|
||||
这个问题就是个开场白,简要说明一下,问题都不大,这个面试官就是第一次打电话给我面试的那个boss,所以技术那块boss心里也有个底细,所以没再问技术问题。
|
||||
|
||||
2.一个业务场景,面对产品不断迭代,以及需求的变动该怎么应对,具体技术方案实现。
|
||||
具体业务场景,我就不一一描述,Boss在白板上画了一个大致的模块图,然后做了一些需求描述。
|
||||
然后需求一层一层的改变,然后往下挖,主要是考察应对产品能力,以及对代码的可维护性和可拓展性这些考察,开放性问题,我觉得还考察一些沟通交流方面的能力,因为有些地方面试官故意说得很含糊,反正就是一个综合能力,以及对产品的理解,中间谈到怎么实现,也问到了一些具体的点,记得问到的有一下几个。
|
||||
|
||||
① 怎么获取一个元素到视图顶部的距离。
|
||||
② getBoundingClientRect获取的top和offsetTop获取的top区别
|
||||
③事件委托
|
||||
|
||||
第二个面试官
|
||||
1.业务场景:比如说百度的一个服务不想让阿里使用,如果识别到是阿里的请求,然后跳转到404或者拒绝服务之类的?
|
||||
主要是考察http协议头Referer,然后怎么判断是阿里的ip或者啥的,我也不太清楚。
|
||||
|
||||
2.二分查找的时间复杂度怎么求,是多少
|
||||
。。。排序的还算清楚一点,查找真的不知所措,没回答上来,也没猜,意义不大,不会就是不会。
|
||||
|
||||
3.XSS是什么,攻击原理,怎么预防。
|
||||
这个很简单,跨站脚本攻击XSS(cross site scripting),攻击类型主要有两种:反射型和存储型,简单说了一下如何防御:
|
||||
|
||||
①转义
|
||||
②DOM解析白名单
|
||||
③第三方库
|
||||
④CSP
|
||||
|
||||
自己对web安全这块系统学习过,前前后后大约了解了很多,对于XSS,CSRF,点击劫持,Cookie安全,HTTP窃听篡改,密码安全,SQL注入,社会工程学都有一定了解,所以这个自然也不在话下。
|
||||
|
||||
4.线性顺序存储结构和链式存储结构有什么区别?以及优缺点。
|
||||
我是类比JS数组和对象来回答的,反正还算凑合吧,自己都数据结构这块多少还是有些印象,所以入了前端,对数据结构和算法确实一直淡忘了。
|
||||
|
||||
5.分析一下移动端日历,PC端日历以及桌面日历的一些不同和需要注意的地方。
|
||||
这个我能想到的大致都说了一遍,不同的场景交互和细节以及功能都有所偏差,以及功能的侧重都可能不同。
|
||||
|
||||
6.白板写代码,用最简洁的代码实现数组去重。
|
||||
我写了两种实现方式:
|
||||
ES6实现:
|
||||
|
||||
[...new Set([1,2,3,1,'a',1,'a'])]
|
||||
ES5实现:
|
||||
|
||||
[1,2,3,1,'a',1,'a'].filter(function(ele,index,array){
|
||||
return index===array.indexOf(ele)
|
||||
})
|
||||
7.怎么实现草稿,多终端同步,以及冲突问题?
|
||||
这个回答的不算好,本来也想到类比git的处理方式,但是说的时候往另外一个方面说了,导致与面试官想要的结果不一样。
|
||||
|
||||
最后说目前的工作经验达不到P6水平,业务类稍弱,阿里现在社招只要P6的高级工程师,但是可以以第二梯队进去,就是以第三方签署就业协议,一年后可以转正,就是俗称的外包。多少还是有点遗憾,面了四轮面了个外包,最后放弃这份工作了。
|
||||
|
||||
最后,感谢boss一直以来的关照和器重。
|
||||
|
||||
学习前端的同学们,欢迎加入前端学习交流群
|
||||
|
||||
前端学习交流QQ群:461593224
|
Loading…
Reference in New Issue
Block a user