js严格模式
1.在严格模式下不支持使用 “arguments.callee / arguments.callee.caller” (Uncaught TypeError: ‘caller’, ‘callee’, and ‘arguments’ properties may not be accessed on strict mode functions or the arguments objects for calls to them)
2.在严格模式下ARGUMENTS和形参没有映射机制
3.在严格模式下不允许给一个对象设置重复属性名的:“obj={n:10,n:20}”
4.在严格模式下,函数执行,如果没有明确指定执行的主体(函数前面没有点),不再像非严格模式下一样,统一都交给window,而是让this指向undefined,代表没有执行主体:“严格模式下,有执行主体this就指向谁,没有执行主体,this就是undefined”
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 ~function () {
/*function fn(x) {
arguments[0]=100;
console.log(x);//=>100 存在映射机制
}
fn(10);*/
/*var obj={
n:10,
n:20
};
console.log(obj.n);*/
function fn() {
console.log(this);//=>window
}
fn();
}();
~function () {
;
/*function fn(x) {
arguments[0]=100;
console.log(x);//=>10 不存在映射机制
}
fn(10);*/
/*var obj={
n:10,
n:20
};
console.log(obj.n);*/
function fn() {
console.log(this);//=>undefined
}
fn();
}();
原型设计模式
在实际项目基于面向对象开发的时候(构造原型设计模式),我们根据需要,很多时候会重定向类的原型(让类的原型指向自己开辟的堆内存
- 自己开辟的堆内存中没有constructor属性,导致类的原型构造函数缺失(解决:自己手动在堆内存中增加constructor属性)
- 当原型重定向后,浏览器默认开辟的那个原型堆内存会被释放掉,如果之前已经存储了一些方法或者属性,这些东西都会丢失(所以:内置类的原型不允许重定向到自己开辟的堆内存,因为内置类原型上自带很多属性方法,重定向后都没了,这样是不被允许的)
less
它是CSS预编译语言,和它类似的还有sass/stylus…
css是标记语言,不是编程语言,没有类、实例、函数、变量等东西;而less等预编译语言就是让css具备面向对象编程的思想;但是浏览器不能直接识别和渲染less代码,需要我们把less代码预先编译为正常的css后,再交给浏览器渲染解析;
less的编译
- 在开发环境下编译(产品没有开发完,正在开发中,这个是开发环境)
导入less.js即可
1
2
3
4
5//=>rel="stylesheet/less" 这块有修改
<link rel="stylesheet/less" href="css/demo1.less">
//=>导入JS文件即可
<script src="js/less-2.5.3.min.js"></script>
在生产环境下编译(产品开发完成了,需要部署到服务器上)
项目上线,不能把less部署,这样用户每一次打开页面都需要重新的编译,非常耗性能,我们部署到服务器上的是编译后的css
1
2
3
4
5
6
7
8
91.在当前电脑的全局环境下安装less模块
$ npm install less -g
验证是否安装成功:$ lessc -v
2.基于命令把我们的less编译成css
$ lessc xxx/xxx.less xxx/xxx.min.css -x
把指定目录中的less编译成为css(并且实现了代码的压缩),把编译后的css存入到具体指定路径中的文件中;上线前在HTML中导入的是css文件;目前基于webpack和框架实现工程化开发的时候,我们都是在webpack配置文件中,配置出less的编译(需要安装less/less-loader等模块),这样不管是开发环境下的预览,还是部署到生产环境下,都是基于webpack中的less模块编译的
less语法:[http://lesscss.cn/]
call、aplly、bind
call
[fn].call([this],[param]…)
fn.call:当前实例(函数FN)通过原型链的查找机制,找到Function.prototype上的call方法 =>function call(){[native code]}
,当call方法执行的时候,内部处理了一些事情
1、首先把要操作函数中的THIS关键字变为CALL方法第一个传递的实参值
2、把CALL方法第二个及第二个以后的实参获取到
3、把要操作的函数执行,并且把第二个以后的传递进来的实参传给函数
1 | // call 原理 |
call细节
- 非严格模式下,如果参数不传,或者第一个传递的是null/undefined,THIS都指向WINDOW
- 在严格模式下,第一个参数是谁,THIS就指向谁(包括null/undefined),不传THIS是undefined
1 | fn.call(obj, 10, 20);//=>this:obj a=10 b=20 |
apply
和call基本上一模一样,唯一区别在于传参方式
- fn.call(obj,10,20)
- fn.apply(obj,[10,20]) APPLY把需要传递给FN的参数放到一个数组(或者类数组)中传递进去,虽然写的是一个数组,但是也相当于给FN一个个的传递
bind:
语法和call一模一样,唯一的区别在于立即执行还是等待执行
- fn.call(obj,10,20) 改变FN中的THIS,并且把FN立即执行
- fn.bind(obj,10,20) 改变FN中的THIS,此时的FN并没有执行(不兼容IE6~8)
解构赋值
对象解构赋值
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 let obj = {name: 'xxx', age: 25, sex: 0};
let {name, age} = obj;//=>对象解构赋值默认情况下要求:左侧变量名和对象中的属性名一致才可以
console.log(name, age);
let {sex} = obj;
console.log(sex);//=>0
let {age: ageAA} = obj;
console.log(age);//=>Uncaught ReferenceError: age is not defined
console.log(ageAA);//=>25 给解构的属性名起别名作为我们使用的变量
let {friend = 0} = obj;
console.log(friend);//=>0 给不存在的属性设置默认值
let fn = function ({
name = '珠峰',
age = 0
} = {}) {//=>把传递的对象解构了(不传递值,默认赋值为空对象:现在传递对象或者不传递,形参接收到的都是对象),解构的时候,可以把传递进来对象中,如果某个属性不存在,我们赋值默认值
console.log(name, age);
};
fn({
name: 'xxx',
age: 25
});
数组解构赋值
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 let a = 12,
b = 13;
//=>a&b互换位置
[a, b] = [b, a];//=>[13,12]
console.log(a, b);
/*let c=a;
a=b;
b=c;
console.log(a, b);*/
/*a=a+b;
b=a-b;
a=a-b;
console.log(a, b);*/
let ary = [12];
let [a, b = 0] = ary;//=>在解构的时候可以给变量设置默认值:如果当前变量对应结构中的这一项没有值,变量用默认值
console.log(a, b);//=>12 0
let ary = [12, 23, 34, 45, 56];
//=>需求:获取第一项,把剩下的项作为一个数组返回
let [a, ...b] = ary;
console.log(a, b);//=>12 [23,34,45,56] “...”在此处称之为剩余运算符:除了前面以外的项,都放在一个数组中
// let [a, ...b, c] = ary;//=>Uncaught SyntaxError: Rest element must be last element 剩余运算符处于解构中最后的位置
-------------------------------------
let a=ary[0],
b=ary[1],
c=ary[2];
let [a, b, c] = ary;//=>让等号左边出现和右边相同的数据结构,左边可以创建一些变量快速获取到右侧对应位置的值(解构赋值)
console.log(a, b, c);
let [a] = ary;
console.log(a);//=>12
let [a, , c] = ary;
console.log(a, c);//=>12 34
‘…’运算符
“…”在ES6的语法中,三个点有三种含义
- 1.剩余运算符
- 2.拓展运算符
- 3.展开运算符:把数组(对象/类数组)中的每一项展开 xxx,xxx,xxx…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 let ary = [12, 23, 34];
let [...arg] = ary; //=>ary.slice(0)
function fn(context, ...arg) {
//=>获取传递值中的第一个和剩下的
console.log(context, arg);
//=>ARG是一个数组 / ARGUMENTS是类数组
}
function sum(...arg) {
//=>传递几个实参,ARG中就存储多少个,此时的ARG和ARGUMENTS一样的,区别是ARG是一个数组,ARGUMENTS是一个类数组
}
-------------------------------------------------------
let ary = [12, 23, 34];
let fn = function (a, b, c) {
console.log(a, b, c);
};
// Math.max(...ary);//=>Math.max(12,23,34)
// fn(ary);//=>a:ary b/c:undefined
fn(...ary);//=>fn(12, 23, 34) 把数组中的每一项分别传递给一个函数,此时我们使用展开运算符把数组展开即可
let obj = {name: 'xxx', age: 20};
let newObj = {...obj, sex: 0};//=>{name: 'xxx', age: 20,sex:0} 把原有对象展开(克隆)放到新对象中
// let ary = [12, 23];
// let newAry = [...ary, 100];//=>[12, 23, 100]
DOM的映射机制
- 页面中的HTML元素,和JS中通过相关方法获取到的元素集合或者元素对象存在映射关系(一个改另外一个会跟着自动修改)
* - xxx.style.color=’red’ : 把xxx元素对象对应堆内存中的style属性下的color属性值修改为’red’(本质操作的是JS堆内存) ;但是由于DOM映射关系,页面中的标签和XXX元素对象是绑在一起的,我们修改元素对象空间的值,页面中的元素会按照最新的值进行渲染;
* - 在元素绑定前,我们获取容器中元素,得到一个空的元素集合,元素数据绑定后,我们不需要重新获取,DOM的映射机制会帮我们把新增加的元素映射到之前获取的空集合中,让其变为有元素的集合(querySelectorAll获取的集合是静态集合(staticNodeList),不存在上述所谓的映射机制,所以基于这种办法,数据绑定完成后需要重新的获取一次才可以)
* - appendChild在追加元素对象的时候,如果这个元素之前容器中已经存在,此时不是克隆一份新的追加到末尾,而是把原有的元素移动到末尾位置