类型转换
- Number(mix)
- parseInt(string,radix) // 以radix进制转换
- parseFloat(string)
- toString(radix) //undefined null 不能用, 转换为radix进制
- String(mix)
- Boolean()
隐式类型转换
- isNaN() //用于检查其参数是否是非数字值。
- ++/-- +/- (一元正负) //先执行Number() 再运算
-
- // 当有一侧为字符串时, 调用String()
- -*/% // Number()
- && || !
-
< <= >=
- == !=
注意:
undefined >1
undefined <1
undefined ==1
null>1
null<1
null=1
NaN
== NaN
都为false
undefined == null
为true
不发生类型转换
- ===
- !==
注意:
- typeof(typeof(a)) // 返回string。 typeof的返回值是string类型
函数
- 方式1 函数声明
function theFirstName() {
}
- 方式2 函数表达式
//命名函数表达式
var test = function abc() {
document.write('a');
}
// 匿名函数表达式 --- 函数表达式
var demo = function () {
document.write('b');
}
参数
- 形式参数 – 形参 实际参数 – 实参
实参数组:arguments
形参数组:函数名
预编译
imply
global
暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就为全局对象所有。
a = 123;
var a = b = 123;
- 一切声明的全局变量,全是window的属性。
var a = 123; // window.a = 123;
预编译四部曲:(预编译发生在函数执行前一刻)
- 创建AO对象(Activation Object)(执行期上下文)
- 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
- 将实参值和形参统一
- 在函数体里面找函数声明,值赋予函数体
示例代码1:
<script>
function fn(a) {
console.log(a);
var a = 123;
console.log(a);
function a () {}
console.log(a);
var b = function () {}
console.log(b);
function d() {}
}
fn(1);
</script>
执行结果:
示例预编译过程:
-
创建AO对象:找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
AO {
a : undefined,
b : undefined,
} -
将实参值和形参统一
AO {
a : 1,
b : undefined,
} -
在函数体里面找函数声明,值赋予函数体
AO {
a : function a () {},
b : undefined,
d : function d() {},
} -
预编译完成,开始执行函数
-
根据AO对象: 第一个
console.log(a);
输出:function a () {}
-
根据
var a = 123;
AO对象修改为:
AO {
a : 123,
b : undefined,
d : function d() {},
}
第二个console.log(a);
输出:123
-
后面
function a () {}
函数声明提升了,不用管。 -
第三个
console.log(a);
还是输出:123
-
根据
var b = function () {}
AO对象修改为:
AO {
a : 123,
b : function () {},
d : function d() {},
} -
可知第四个
console.log(b);
输出:function () {}
示例代码2:
<script>
function test(a,b) {
console.log(a);
c = 0;
var c;
a = 3;
b = 2;
console.log(b);
function b () {}
function d () {}
console.log(b);
}
test(1);
</script>
结果:
全局 预编译
var a = 123;
function a () {
}
生成一个GO对象 Global Object
GO {
a: undefined
} // GO === window
示例题目1:
<script>
a = 100;
function demo(e) {
function e() {}
arguments[0] = 2;
console.log(e);
if(a) {
var b = 123;
function c() {
}
}
var c;
a = 10;
var a;
console.log(b);
f = 123;
console.log(c);
console.log(a);
}
var a;
demo(1);
console.log(a);
console.log(f);
</script>
结果:
示例题目2:
<script>
var str = false + 1;
console.log(str);
var demo = false == 1;
console.log(demo);
if(typeof(a) && -true + (+undefined) + ""){
console.log('基础扎实');
} // "undefined" "NaN"
if( 11 + "11" * 2 == 33 ) {
console.log('基础扎实');
}
!!" " + !!"" - !!false || console.log('你觉得能打印,你就是猪');
</script>
输出结果:
作用域,作用域链
-
[[scope]]:每个javascript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供javascript引擎存取,[[scope]]就是其中一个。
[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合。 -
作用域链:[[scope]] 中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。
-
运行期上下文:当函数执行时,会创建一个称为执行期上下文(AO)的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁。
-
查找变量:从作用域链的顶端依次向下查找。
闭包
- 当内部函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄露(就是内存被占用,导致可用的越来越少)
闭包的作用
- 实现公有变量: 函数累加器
<script>
function add() {
var count = 0;
function demo() {
count ++;
console.log(count);
}
return demo;
}
var counter = add();
counter();
counter();
</script>
- 可以做缓存 (存储结构): eater
<script>
function eater() {
var food = "";
var obj = {
eat : function () {
console.log("i am eating " + food);
food = "";
},
push : function (myFood) {
food = myFood;
}
}
return obj;
}
var eater1 = eater();
eater1.push('banana');
eater1.eat();
</script>
- 可以实现封装,属性私有化: Person()
<script>
function Deng(name, wife) {
var prepareWife = "xiaozhang";
this.name = name;
this.wife = wife;
this.divorce = function() {
this.wife = prepareWife;
}
this.changePrepareWife = function(target) {
prepareWife = target;
}
this.sayPrepareWife = function() {
console.log(prepareWife);
}
}
var deng = new Deng('deng','xiaoliu');
</script>
- 模块化开发,防止污染全局变量
立即执行函数
定义:此类函数没有声明,在一次执行过后即释放。适合做初始化工作。
(function (){}()); // W3C建议第一种
(function (){})();
注意:只有表达式才能被执行符号执行
function test() {
var a = 123; //报错,语法错误
}()
var test = function () {
console.log('a'); //正确,输出a
}()
闭包题目
<script>
function test() {
var arr = [];
for(var i = 0; i<10; i++) {
(function (j) {
arr[j] = function () {
document.write(j + "");
}
}(i));
}
return arr;
}
var myArr = test();
for(var j = 0; j<10; j++) {
myArr[j]();
}
</script>
输出结果:
0123456789
面试题:
题目1:
<script>
var x =1;
if(function f() {}) {
x += typeof f;
}
console.log(x);
</script>
输出:
1undefined
原因: if 里面的函数因为外面的括号变成了表达式,因此里面的f未定义。