0%

签名 Cookie:Sign

  • def 令牌,用于验证用户身份和登录状态的标识
  • 优点:验证 cookie 所需的一切信息都存储在 cookie 中;cookie 可以包含额外的信息(additional infomation),并且对这些信息进行签名也很容易
  • 缺点:正确地处理签名很难。很容易忘记对数据进行签名,或者忘记验证数据的签名,从而造成安全漏洞

令牌 Cookie:Token

  • ** 签名,** 服务端在接受用户请求时,判断该请求是否来自于自己允许的平台(自己允许的平台有统一的加密规则,防止请求在客户端发出后被拦截)

  • 优点:添加信息非常容易。cookie 的体积非常小,因此移动终端和速度较慢的客户端可以更快地发送请求

  • 缺点:需要在服务器中存储更多信息。如果使用的是关系数据库,那么载入和存储 cookie 的代价可能会很高

简单动态字符串(simple dynamic string,SDS)

定义

  • redis 的默认字符表示,作为一个可被修改的字符串值

  • 作为字符串的底层实现

1
2
3
4
5
6
7
struct sdshdr
{
/* data */
int len; -- 数组已使用字节数量
int free; -- 数组未使用字节数量
char buf[]; -- 字节数组
};

注:buf [] 的最后一个字节会用于保存空字符’\0’(同 C style)

使用 SDS 而非 C style 字符串的好处

获取字符串长度不为性能瓶颈

  • 由定义可知,SDS 的结构体中已经保存了数组的长度(len),从而只需使用 STRLEN () 获取值,其对应算法复杂度始终仅为 O (1);C 字符串由于没有保存该信息,则需要对数组进行遍历得到长度,其算法复杂度为 O (n)

API 安全,排除了缓冲区溢出的风险

  • 对于 C 字符串而言,缓冲区容易溢出其实是不记录数组长度的衍生问题。如考虑下述场景:

1
char *strcat(char *c1, const char *c2);

​ strcat () 方法会假定系统尚且分配了足够的内存给 c1,以容纳 c2 中的所有内容;而 c2 数组长度过长且超出内存限制时,就造成了缓冲区的溢出。这可能会给相邻内存的内容带来意外的后果(如:未指定的意外修改,etc.)

​ 而 SDS 的 API 会自动对 len 进行修改和更新;当当前空间不能满足要求时,则会自动扩展当前 SDS 的空间。对应 redis 中字符串拼接方法为:

1
sdscat(c1, c2);

是二进制安全的

​ 既可存储文本数据、也可存储二进制数据

兼容部分 C style 字符串

1
2
// string compare
strcasecmp(c1->c2, "hello world");

用途

  • 作为数据库中字符串值、整数值和浮点数值的存储

1
2
RPUSH fruits "apple" "banana" "cherry"
-- output:(integer) 3
  • 作为缓冲区(buffer)

空间分配策略

目的

​ 减少连续执行字符串增长操作所需的内存重分配次数

  • 策略 1:空间预分配

    • 当未使用空间足够时,无需进行内存重分配,即没有对字符串进行修改
    • 若修改后的字符串长度小于 1MB,将分配与当前数组已使用长度等长的未使用空间
    • 若修改后的字符串长度大于 1MB,将分配 1MB 的未使用空间
  • 策略 2:惰性空间释放

    • 当空间被释放成为空余空间后,并不会立即对其进行回收,而是先由 free 属性记录下来
    • 避免了缩短字符串时所需的内存重分配操作,并为将来可能有的增长操作提供了优化
    • 当有实际空间需要时,会通过对应 API 真正完成空余空间的释放

字符串操作

自增 / 自减

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import redis

# 获取连接
conn = redis.Redis()
# 获取对应key:只要该字符串值可以被解释为整数值,则可进行下述处理

conn.get('sample_key')
# 对该key进行自增操作 incr = short for increase
conn.incr('sample_key')
# 也可以以数字形式指定自增参数,下两者效果相同
# INCRBY sample_key 10
conn.incr('sample_key', 10)

# 对该key进行自减操作 decr = short for decrease
# DECRBY sample_key 8
conn.decr('sample_key', 8)

# 二次获取当前的数值
conn.get('sample_key')

打包 (package) 处理结构化数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import redis
# 建立连接
conn = redis.Redis(host='127.0.0.1', port=6379, password='123456')
# 执行APPEND命令:返回的是当前字符串的长度
# 此时前者可不存在或为空串,则得到的新字符串长度显然为后者的长
conn.append('sample_string', 'hello ')
conn.append('sample_string', 'world!')
# 操作后sample_string的长度:12

# SUBSTR:获取字符串子串(部分区间值)
# redis数组索引也是从0开始,则取得的值为llo
conn.substr('sample_string', 2, 4)

# SETRANGE:为字符串设置范围
# 设置后仅改变输出的字符串内容
# 字符串长度仍为总长度,而非处理后的范围长度
conn.setrange('sample_string', 0, 'H')

# SETBIT:单独改变某二进制位

【参考】
[1] 《Redis 的设计与实现》

[2] 《Redis 实战》

简单工厂模式

案例

​ 使用简单工厂模式模拟女娲(Nvwa)造人(Person),如果向造人的工厂方法传入参数”M“,则返回一个男人(Man)对象,如果传入参数”W“,则返回一个女人(Woman)对象,绘制相应的类图并使用 Java 语言模拟实现该场景。现需要增加一个新的机器人(Robot),如果传入参数为 “R”,则返回一个机器人对象,对代码进行修改并注意 “女娲 “类的变化。

抽象产品类

1
2
3
4
5
6
7
8
/**
* Person.java
* @author Vincent
* 抽象产品类
*/
public interface Person {
}

具体产品

1
2
3
4
5
6
7
8
9
10
11
/**
* Man.java
* @author Vincent
* 具体产品类:男人
*/
public class Man implements Person {
public Man() {
System.out.println("男人对象已创建!");
}
}

1
2
3
4
5
6
7
8
9
10
11
/**
* Woman.java
* @author Vincent
* 具体产品类:女人
*/
public class Woman implements Person {
public Woman() {
System.out.println("女人对象已创建!");
}
}

1
2
3
4
5
6
7
8
9
10
11
/**
* Robot.java
* @author Vincent
* 具体产品类:机器人
*/
public class Robot implements Person {
public Robot() {
System.out.println("机器人对象已创建!");
}
}

工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* Nvwa.java
* @author Vincent
* 工厂类:女娲
*/
public class Nvwa {
private static String PERSON_TYPE_MAN = "M";
private static String PERSON_TYPE_WOMAN = "W";
private static String PERSON_TYPE_ROBOT = "R";

public static Person makePerson(String type) {
if (PERSON_TYPE_MAN.equalsIgnoreCase(type)) {
System.out.println("返回一个男人对象!");
return new Man();
} else if (PERSON_TYPE_WOMAN.equalsIgnoreCase(type)) {
System.out.println("返回一个女人对象!");
return new Woman();
} else if (PERSON_TYPE_ROBOT.equalsIgnoreCase(type)) {
System.out.println("返回一个机器人对象!");
return new Robot();
}
return null;
}
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* Client.java
* @author Vincent
* 客户端类
*/
public class Client {
public static void main(String[] args) {
//通过静态工厂方法创建产品
Scanner sc = new Scanner(System.in);
String type = sc.next();

//创建并获取对象
try {
Nvwa.makePerson(type);
} catch (Exception e) {
e.toString();
}
}
}

小结

角色

  • 工厂 - Nvwa

  • 抽象产品 - Person

  • 具体产品 - Man、Woman 和 Robot

特点

  • 工厂类包含必要的逻辑判断,以选择生产具体产品

  • 用于单个产品生产

优点

  • 实现了对象创建和使用的分离

  • 客户端只需要知道具体产品类对应参数,而无需知道所创建具体产品类的类名

  • 引入配置文件可在不修改任何客户端代码的情况下更换 / 增加新的具体产品类,提高了系统的灵活性

缺点

  • 工厂类职责过重

  • 增加了系统的复杂度

  • 静态工厂方法无法形成基于继承的等级结构,系统不易扩展

适用环境

  • 工厂类负责创建的对象比较少

  • 客户端不关心对象创建的细节

工厂方法模式

案例

​ 同上:使用简单工厂模式模拟女娲(Nvwa)造人(Person),如果向造人的工厂方法传入参数”M“,则返回一个男人(Man)对象,如果传入参数”W“,则返回一个女人(Woman)对象,绘制相应的类图并使用 Java 语言模拟实现该场景。现需要增加一个新的机器人(Robot),如果传入参数为 “R”,则返回一个机器人对象,对代码进行修改并注意 “女娲 “类的变化。

抽象产品类

1
2
3
4
5
6
7
8
/**
* Person.java
* @author Vincent
* 抽象产品类
*/
public interface Person {
}

具体产品

1
2
3
4
5
6
7
8
9
10
11
/**
* Man.java
* @author Vincent
* 具体产品类:男人
*/
public class Man implements Person {
public Man() {
System.out.println("男人对象已创建!");
}
}

1
2
3
4
5
6
7
8
9
10
11
/**
* Woman.java
* @author Vincent
* 具体产品类:女人
*/
public class Woman implements Person {
public Woman() {
System.out.println("女人对象已创建!");
}
}

1
2
3
4
5
6
7
8
9
10
11
/**
* Robot.java
* @author Vincent
* 具体产品类:机器人
*/
public class Robot implements Person {
public Robot() {
System.out.println("机器人对象已创建!");
}
}

抽象工厂

1
2
3
4
5
6
7
8
9
10
11
12
/**
* Factory.java
* @author Vincent
* 抽象工厂类
*/
public interface PersonFactory {
/**
* @return 人对象
*/
Person makePerson();
}

具体工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* ManFactory.java
* @author Vincent
* 具体工厂类:男人工厂
*/
public class ManFactory implements PersonFactory {
private static String PERSON_TYPE_MAN = "M";

@Override
public Person makePerson() {
System.out.println("返回一个男人对象!");
return new Man();
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* WomanFactory.java
* @author Vincent
* 具体工厂类:女人工厂
*/
public class WomanFactory implements PersonFactory {
private static String PERSON_TYPE_WOMAN = "W";

@Override
public Person makePerson() {
System.out.println("返回一个女人对象!");
return new Woman();
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* RobotFactory.java
* @author Vincent
* 具体工厂类:机器人工厂
*/
public class RobotFactory implements PersonFactory {
private static String PERSON_TYPE_ROBOT = "R";

@Override
public Person makePerson() {
System.out.println("返回一个机器人对象!");
return new Robot();
}
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* Client.java
* @author Vincent
* 客户端类
*/
public class Client {
public static void main(String[] args) {
//通过工厂方法创建产品
Scanner sc = new Scanner(System.in);
String type = sc.next();

//创建并获取对象
PersonFactory factory = null;
switch (type) {
case "M": factory = new ManFactory(); break;
case "W": factory = new WomanFactory(); break;
case "R": factory = new RobotFactory(); break;
default:
System.out.println("输入有误!");
exit(0);
}
factory.makePerson();
}
}

小结

角色

  • 抽象产品 - Person

  • 具体产品 - Man、Woman 和 Robot

  • 抽象工厂 - PersonFactory

  • 具体工厂 - ManFactory、WomanFactory 和 RobotFactory

特点

  • 一个产品对应一个工厂类

  • 用于生产某种类型产品

优点

  • 工厂方法不仅创建客户所需要的产品,还隐藏了具体产品类的实例化细节

  • 能让工厂自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部

  • 在系统中加入新产品时,完全符合开闭原则。

缺点

  • 系统中类的个数将成对增加,增加了系统的复杂度

  • 增加了系统的抽象性

适用环境

  • 抽象工厂类通过子类来指定创建对象

  • 客户端不知道所需要对象的类

抽象工厂模式

案例

​ 一个电器工厂可以产生多种类型的电器,如海尔工厂可以生产海尔电视机、海尔空调等,TCL 工厂可以生产 TCL 电视机、TCL 空调等,相同品牌的电器构成一个产品族,而相同类型的电器构成了一个产品等级结构,现使用抽象工厂模式模拟该场景。

抽象产品类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* AirConditioner.java
* @author Vincent
* 抽象产品类:空调
*/
public interface AirConditioner {
/**
* 开启
*/
public void on();

/**
* 关闭
*/
public void off();

/**
* 调节室温
*/
public void changeTemperature();

/**
* 调节风速
*/
public void changeBlowingSpeed();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* Television.java
* @author Vincent
* 抽象产品类:电视
*/
public interface Television {
/**
* 开启
*/
public void on();

/**
* 关闭
*/
public void off();

/**
* 切换频道
*/
public void switchChannel();

/**
* 调节音量
*/
public void changeVolume();
}

具体产品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* HaierAirConditioner.java
* @author Vincent
* 具体产品类:海尔空调
*/
public class HaierAirConditioner implements AirConditioner {
@Override
public void on() {
System.out.println("海尔空调已启动");
}

@Override
public void off() {
System.out.println("海尔空调已关闭");
}

@Override
public void changeTemperature() {
System.out.println("您正在使用海尔空调调节室温");
}

@Override
public void changeBlowingSpeed() {
System.out.println("您正在使用海尔空调调节风速");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* HaierTelevision.java
* @author Vincent
* 具体产品类:海尔电视
*/
public class HaierTelevision implements Television {
@Override
public void on() {
System.out.println("海尔电视已启动");
}

@Override
public void off() {
System.out.println("海尔电视已关闭");
}

@Override
public void switchChannel() {
System.out.println("您正在海尔电视切换频道");
}

@Override
public void changeVolume() {
System.out.println("您正在海尔电视调节音量");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* TCLAirConditioner.java
* @author Vincent
* 具体产品类:TCL空调
*/
public class TCLAirConditioner implements AirConditioner {
@Override
public void on() {
System.out.println("TCL空调已启动");
}

@Override
public void off() {
System.out.println("TCL空调已关闭");
}

@Override
public void changeTemperature() {
System.out.println("您正在使用TCL空调调节室温");
}

@Override
public void changeBlowingSpeed() {
System.out.println("您正在使用TCL空调调节风速");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* TCLTelevision.java
* @author Vincent
* 具体产品类:TCL电视
*/
public class TCLTelevison implements Television {
@Override
public void on() {
System.out.println("TCL电视已启动");
}

@Override
public void off() {
System.out.println("TCL电视已关闭");
}

@Override
public void switchChannel() {
System.out.println("您正在使用TCL电视切换频道");
}

@Override
public void changeVolume() {
System.out.println("您正在使用TCL电视调节音量");
}
}

抽象工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Factory.java
* @author Vincent
* 抽象工厂类
*/
public interface Factory {
/**
* 返回一台空调
* @return AirConditioner
*/
public AirConditioner produceAirConditioner();

/**
* 返回一台电视
* @return Television
*/
public Television produceTelevision();
}

具体工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* HaierFactory.java
* @author Vincent
* 具体工厂类:Haier工厂
*/
public class HaierFactory implements Factory {
@Override
public AirConditioner produceAirConditioner() {
return new HaierAirConditioner();
}

@Override
public Television produceTelevision() {
return new HaierTelevision();
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* TCLFactory.java
* @author Vincent
* 具体工厂类:TCL工厂
*/
public class TCLFactory implements Factory {
@Override
public AirConditioner produceAirConditioner() {
return new TCLAirConditioner();
}

@Override
public Television produceTelevision() {
return new TCLTelevison();
}
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* Client.java
* @author Vincent
* 客户端类
*/
public class Client {
public static void main(String[] args) {
// 使用抽象层定义
Factory factory = null;
AirConditioner airConditioner;
Television television;

// 获取具体工厂对象
try {
factory = (HaierFactory)XMLUtil.getBean();
} catch (Exception e) {
e.toString();
}

// 获取具体产品对象
airConditioner = factory.produceAirConditioner();
television = factory.produceTelevision();

// 调用具体产品方法
airConditioner.on();
airConditioner.changeTemperature();
airConditioner.changeBlowingSpeed();
airConditioner.off();
System.out.println("----------------------");
television.on();
television.switchChannel();
television.changeVolume();
television.off();
}
}

小结

角色

  • 抽象产品 - Television、AirConditioner

  • 具体产品 - Haier、TCL 对应产品族

  • 抽象工厂 - 创建 Television、AirConditioner 产品等级结构

  • 具体工厂 - Factory

特点

  • 用于生产一系列产品

优点

  • 隔离了具体类的生成

  • 当同产品族中多个对象一起工作时,能保证客户端始终只使用同一个产品族中的对象

  • 增加新的产品族无须修改已有系统,符合开闭原则

缺点

  • 又违背了开闭原则:不易增添新的产品等级结构,需要对原有系统进行较大的修改

适用环境

  • 每次只使用某一产品族

  • 同产品族产品一起使用

  • 产品等级结构稳定

this 的指向问题

​ 作为一门一切皆为对象的语言,首先需要搞明白指针 this 的指向问题。以下为常见的两种指向情况:

作为构造函数调用

题型 1

1
2
3
4
5
6
7
8
9
var foo = "123";

function print() {
var foo = "456";
this.foo = "789";
console.log(foo);
}

print();

我的答案: 456

  • 通过 print () 函数,可以生成一个新对象。这时,this 就指这个新对象,this.foo 就作为这个新对象的成员

纯粹的函数调用

题型 2

1
2
3
4
5
6
7
8
9
10
11
var a = 5;

function test() {
a = 0;

alert(a);
alert(this.a);

var a;
alert(a);
}

我的答案: 弹出 0,5,0

  • 全局性调用,因此 this 就代表全局对象,this.a 则调用全局变量 a,故弹出结果为 5

其余详见:Javascript 的 this 用法 - 阮一峰的网络日志 (ruanyifeng.com),讲的很透彻

鼠标事件与键盘事件

题型:下列事件哪个不是由鼠标触发的事件()

A click

B contextmenu

C mouseout

D keydown

我的答案: D

鼠标事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//1.鼠标点击左键触发
onclick
//2.鼠标经过触发
onmouseover
//3.鼠标离开触发
onmouseout
//4.获得鼠标焦点触发
onfocus
//5.失去鼠标触发
onblur
//6.鼠标移动触发
onmousemove
//7.鼠标弹起触发
onmouseup
//8.鼠标按下触发
onmousedown
//9.鼠标经过时触发,但是不会冒泡
onmouseenter
//10.鼠标离开时触发,但是不会冒泡
onmouseleave
鼠标事件对象
1
2
3
4
5
6
7
8
9
10
11
12
//1.返回鼠标相对于浏览器窗口可视区的X坐标
e.clientX
//2.返回鼠标相对于浏览器窗口可视区的Y坐标
e.clientY
//3.返回鼠标相对于文档页面的X坐标
e.pageX
//4.返回鼠标相对于文档页面的Y坐标
e.pageY
//5.返回鼠标相对于屏幕的X坐标
e.screenX
//6.返回鼠标相对于屏幕的Y坐标
e.screenY
* 禁用鼠标事件
1
2
3
4
5
6
7
8
//禁止鼠标右键菜单
document.addEventListener('contextmenu',function(e){
e.preventDefault();
})
//禁止鼠标选中
document.addEventListener('selectstart',function(e){
e.preventDefault();
})
键盘事件
1
2
3
4
5
6
//1.某个键盘按键被松开时触发
onkeyup
//2.某个键盘按键被按下时触发
onkeydown
//3.某个键盘被按下时触发,不识别功能键如ctrl、shift etc.
onkeypress

注:onkeypress 区分大小写,onkeydownonkeyup 不区分

作用域问题

题型:

<ul>

<li>click me</li>

<li>click me</li>

<li>click me</li>

<li>click me</li>

</ul>

运行如下代码:

1
2
3
4
5
6
7
var elements = document.getElementsByTagName("li");
var length = elements.length;
for (var i = 0; i < length; i++) {
elements[i].onclick = function () {
alert(i);
};
}

依次点击 4 个 li 标签,哪一个选项是正确的运行结果()

A 依次弹出 1, 2, 3, 4

B 依次弹出 0, 1, 2, 3

C 依次弹出 3, 3, 3, 3

D 依次弹出 4, 4, 4, 4

我的答案: D

  • 在《JavaScript 高级程序设计》有如下解释

    • 这是由于作用域链的这种配置机制引出的一个副作用,即闭包只能取得包含函数中任何变量的最后一个值。闭包所保存的是整个变量对象,而不是某个特殊的变量。
  • 回归具体问题,这里 alert (i) 中绑定的 i 实际上不是 i 的值,而是 i 本身。当循环结束后,因此执行 onclick 事件、执行 alert () 时,本身 onclick 绑定的 function 的作用域中没有变量 i,i 为 w 未定义的 (undefined),则解析引擎会寻找父级作用域,发现父级作用域中有 i,则取得的 i 对应值始终为 4。

如何解决?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//1、利用块级域
for(var i=0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
//2、利用自执行函数传参
for(var i=0; i < 10; i++) {
(function(i) {
setTimeout(function() {
console.log(i);
}, 1000);
})(i);
}
//3、利用设置延时的第三个参数传递
for(var i=0; i < 10; i++) {
setTimeout(function(j) {
console.log(j);
}, 1000, i);
}
//4、利用promise
for(var i=0; i < 10; i++) {
new Promise((resolve, reject) => {
var j = i;
setTimeout(function() {
console.log(j)
}, 1000);
})
}
//5、利用async函数
async function foo() {
for(var i=0; i < 10; i++) {
let result = await new Promise((resolve, reject) => {
setTimeout(function() {
resolve(i);
}, 1000); // 每隔1s打印数字 0 - 9
});
console.log(result);
}
}
foo();

js 中的原始类型

题型:关于 javascript 的原始类型(primitive type),错误的是

A 有 5 种 primitive type,分别是 Undefined、Null、Boolean、Number 和 String。

B var sTemp = “test string”;alert (typeof sTemp); 结果为 string

C var oTemp;alert (oTemp == undefined) 为 true

D alert (null == undefined); 结果为 false

我的答案: D

六大原始类型
  • 数字类型 number

  • 字符串类型 string

  • 布尔类型 boolean

  • 空值 null

  • 未定义 undefined

  • 独一无二类型 (ES6 新增) symbol:引入以防止属性名的冲突

注:其他类型均为引用类型(Object)

最大值的求法

题型:下面求 a 中最大值正确的是 ()

A Math.max(a)

B Array.max(a)

C Math.max.call(null,a)

D Math.max.apply(null,a)

我的答案: D

Math.max
返回一组数中的最大值
Math.max.apply

​ 返回一个对象(如:数组)中的最大值

* 标准事件模型 IE9+

题型:w3c 制定的 javascript 标准事件模型,以下正确的顺序以及描述是?

A 事件捕获 > 事件冒泡

B 事件捕获 -> 事件处理 -> 事件冒泡

C 事件冒泡 -> 事件处理

D 事件处理 -> 事件捕获 -> 事件冒泡

我的答案: B

异步执行调用

题型:以下语句的执行结果是什么?

1
2
3
4
5
6
7
8
9
console.log("one");

setTimeout(function () {
console.log("two");
}, 0);

console.log("three");

console.log("four");

我的答案: “one” “three” “four” “two”

  • 这是由于 setTimeout () 方法是异步执行的。当调用该方法时,会把函数参数与函数体中的内容放入消息队列,直到当前主程序执行完成后,再予以调用

浮点数运算问题

题型:写一个求和的函数 sum,达到下面的效果

1
2
3
4
5
6
7
8
// Should equal 15
sum(1, 2, 3, 4, 5);
// Should equal 0
sum(5, null, -5);
// Should equal 10
sum('1.0', false, 1, true, 1, 'A', 1, 'B', 1, 'C', 1, 'D', 1, 'E', 1, 'F', 1, 'G', 1);
// Should equal 0.3, not 0.30000000000000004
sum(0.1, 0.2);

我的答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function sum() {

var add = 0;

for (var i = 0; i < arguments.length; i++) {

if (!(typeof arguments[i] == "boolean")) {

if (!isNaN(arguments[i])) {

add += Number(arguments[i]);

}

}

}

alert(Math.round(add * 10) / 10);

}
  • 为什么 1+2≠3?因为 js 采用的是 IEEE754 标准处理浮点数,视作双精度数,结果为结果是 0.30000000000000004(计组内容)

样式表的嵌入

题型 1:在以下的 HTML 中,哪个是正确引用外部样式表的方法?

  • A <style src="mystyle.css">

  • B <link rel="stylesheet" type="text/css" href="mystyle.css">

  • C <stylesheet>mystyle.css</stylesheet>

  • D <stylesheet>src=mystyle.css</stylesheet>

我的答案: B

外部样式表
  • 适用场景:样式需应用到多个页面时,可通过引入同一个外部样式表来改变整个网页站点的外观

  • 过程:浏览器从外部样式表中逐一读取样式声明,并藉此格式化文档

1
2
3
4
5
6
7
8
9
<head>
<!--1、链接式-->
<link rel="stylesheet" type="text/css" href="sample_style1.css">
<!--2、导入式-->
<style type="text/css">
@import url(sample_style2.css);
</style>
</head>

题型 2:哪个 HTML 标签用于定义内部样式表?

  • A <style>

  • B <script>

  • C <css>

  • D <html>

我的答案: A

内部样式表(内嵌样式)
  • 适用场景:单个文档需要应用某特殊样式时

1
2
3
4
5
6
7
8
9
10
11
12
13
<head>
<style type="text/css">
p{
text-align: right; /*文本右侧对齐*/
font-size: 12px; /*字体大小 12 像素, 注意这里12与像素px之间不要有空格*/
line-height: 20px; /*行高 20 像素*/
text-indent: 2em; /*首行缩进2个文字大小空间*/
width: 200px; /*段落宽度 200 像素*/
margin: 0 auto; /*浏览器下居中*/
margin-bottom: 10px; /*段落下边距 10 像素*/
}
</style>
</head>
内联样式(行内样式)
  • 适用场景:单个元素需要应用某特殊样式时

1
2
3
4
5
<body>
<p style="background-color: #666666">
this is a sample text
</p>
</body>

注释的使用

题型:如何在 CSS 文件中插入注释?

  • A // this is a comment

  • B // this is a comment //

  • C /* this is a comment */

  • D this is a comment

我的答案: C

注:实际 CSS 中的注释不区分单行与多行,所有被放在 /**/ 分隔符之间的文本信息都被称为注释

选择器的使用

题型:如何为所有的 <h1> 元素添加背景颜色?

  • A h1.all {background-color:#FFFFFF}

  • B h1 {background-color:#FFFFFF}

  • C all.h1 {background-color:#FFFFFF}

  • D #h1 {background-color:#FFFFFF}

我的答案: B

1
2
3
4
5
6
7
8
/*1、通用元素选择器,匹配任何元素*/
* { margin:0; padding:0; }
/*2、标签选择器,匹配所有使用p标签的元素*/
p { font-weight:bold; }
/*3、class选择器,匹配所有class属性中包含info的元素*/
.info { background:#ff0; }
/*4、id选择器,匹配所有id属性等于sample的元素*/
#sample { background:#ff0; }

进阶内容见:CSS 选择器笔记 - 阮一峰的网络日志 (ruanyifeng.com),总结的很全面了

文本样式的控制

题型 1:在以下的 CSS 中,可使所有 <p> 元素变为粗体的正确语法是?

  • A <p style="font-size:bold">

  • B <p style="text-size:bold">

  • C p {font-weight:bold}

  • D p {text-size:bold}

我的答案: C

font-weight
  • 默认为 normal,可能值如下:

    • bold(粗体)
    • bolder(顾名思义,更粗的粗体)
    • lighter(细体)
    • 100~900 的数值:400=normal,700=bold,粗细程度随数值递增

列表的使用

题型:如何产生带有正方形项目的列表?

  • A list-type: square

  • B type: 2

  • C type: square

  • D list-style-type: square

我的答案: D

list-style-type
  • 具体的值有很多,常用 disc(默认,实心圆)none(无) decimal(数字) lower-roman(小写罗马数字)

四种定位方式

题型:HTML 元素默认情况下的定位方式为

  • A static

  • B relative

  • C fixed

  • D absolute

我的答案: A

静态定位 static
  • 相当于没有定位,元素正常出现在文档流中

相对定位 relative
  • 应用此定位的元素会脱离正常的文档流,但其在文档流中的位置依然存在,只是视觉上相对原来的位置有移动

绝对定位 absolute
  • 相对于 static 定位以外的首个父元素进行定位,脱离正常的文档流,且不再占据文档流中的位置

固定定位 fixed
  • 相对于浏览器窗口进行定位

边框与浮动

题型 1:如何显示这样一个边框:上边框 10 像素、下边框 5 像素、左边框 20 像素、右边框 1 像素?

  • A border-width:10px 5px 20px 1px

  • B border-width:10px 20px 5px 1px

  • C border-width:5px 20px 10px 1px

  • D border-width:10px 1px 5px 20px

我的答案: D

border-width 顺序:顺时针,↑→↓←

题型 2:为什么会出现浮动和什么时候需要清除浮动?清除浮动的方式?

解答:

  1. 浮动的出现是因为:如果在标准流下,一个父元素未设置其自身的高度 height 属性,那么它的高度就会被子元素的高度撑开,是出于这样一种自适应的现象;

  2. 需要清除浮动的场景:如 1 中所述,当父元素未设置自身高度而无法达到既定的视觉效果时,需要清除浮动;

  3. 清除浮动的方式有:

    (1)给父元素样式添加 overflow:hidden,从而创建一个 BFC(Block formatting context,块级格式化上下文),从而使其中的元素布局是不受外界的影响,达到清除浮动的目的;

    (2)在父元素的最后设置 clear:both,使得父元素和冗余元素向子元素方向延展,直到子元素边界停止浮动,使得父元素能够成功地包裹住子元素,从而变相地消除了浮动。