变量作用域
var a = 1;
function test(){
var a = 2;
console.log(a);//输出为2
}
test()
在函数外已经声明并赋值a变量,且console输出根据就近原则去a的值。
var a = 1;
function test2(){
console.log(a);//undefined
var a = 2;
}
test2函数上方虽然声明并赋值了a变量,但位于console之下,a变量被提升了,输出时是已经是声明并未赋值的a变量。
var a =1;
function test3(){
console.log(a);//输出为1
a = 3;
}
上方函数作用域中a被重新赋值,但未重新声明,且位于console之下,所以输出全局作用域的a。
let a =1;
function test4(){
console.log(a);//a is not defined
let a =3;
}
上方作用域中使用了ES6的let变量声明a,而let不同与变量var有变量提升的功能,所以报错a is not defined(var变量会离它最近的父函数内创建作用域,而let会在它最近的块级元素中创建作用域,块级如for,if语句和其他块);
function test5(){
let a =1;
{
let a =2;
}
console.log(a);//1
}
上面的函数console输出的是1,因为console没有在块级元素a为2的块级作用域中,而在let a为1的函数作用域中。
2.类型比较
var arg = [],
arg1 = [1];
console.log(arg === arg1);//false
上面代码中数组的比较为false;
var arg = [],
arg1 = [];
sonsole.log(arg === arg1);//false
Why?, 上面两个相同的数组比较为false,因为两个单独的数组永不相等,所以输出为false;
var arr = [];
var array = {};
console.log(typeof(arr)===typeof(array))//true
上面的利用typeof来比较数字和对象,因为typeof获取null,数组,对象都是Object对象类型,所以返回true(真正判断变量类型可以用instanceof,arr instanceof Arrray返回为true)
var array = []
console.log(array instanceof Array);//true
console.log(array instanceof object);//true
上面利用instanceof来判断是否属于那个实例,Arrray既是数组类型也是对象类型,所以返回两次true;
3.this的指向问题重点内容
var foo={
name:'Tom',
prints:function(){
console.log(this.name);
}
}
foo.prints();//Tom
上方的变量foo中调用this是指向本身,所以输出Tom
var foo1 = {
name:"Mary",
prints:function(){
return this.name;
}
}
var names = foo.prints;
console.log(names);//undefined
foo1的方法赋值于一个names变量中,调用时this不再指向foo1对象,而是指向window对象,所以console输出是undefined
var foo = {
name:'Tom',
prints:function(){
return this.name;
}
}
var foo1 = {
name:'Liming'
}
var Prints = foo.prints;
console.log(Prints.apply(foo1));//Liming
foo的方法赋值给Prints变量,但是通过apply把this指向foo1对象中,所以console输出是Liming;
4.函数参数
function test6(){
console.log(Arrray.prototype.slice.call(arguements));//[1,2]
}
test(1,2);
test6函数利用arguments类数组对象获取传入的函数参数数组,所以输出数组参数[1,2]。
function test7(){
return function(){
console.log(Array.prototype.slice.call(arguments));
//未执行到此,所以没有输出。
}
}
test7(7,8);
同样利用arguments来获取参数,但因为没有执行return中的函数,所以无输出。
var args = [1,2];
function test8(){
console.log(Array.prototype.slice.call(arguments));//[1,2,3,4]
}
Array.prototype.push.call(args,3,4);
test8(...args)
上面利用Array.prototype.push.call()向args添加了3,4,并用ES6延展操作法(…),将数组展开并传入到test8中,所以console输出为[1,2,3,4];
5闭包问题
function foo(){
var number = 999;
Add = function(){number+=1};
function foo1(){
console.log(number);
}
return foo1;
}
var result = foo();
result();//999
Add();
result();//1000
闭包问题,根据阮大神的简明就是获取函数内部的变量,foo1方法输出函数中的name,最后返回foo1函数,所以foo函数赋值Result变量,Result输出为999,Add函数调用一次number加1,再次调用number为1000;
var elem = document.getElementsByTagName('div'); // 如果页面上有5个div
for(var i = 0; i < elem.length; i++) {
(function (w) {
elem[w].onclick = function () {
alert(w); // 依次为0,1,2,3,4
};
})(i);
}
在绑定点击事件外部封装一个立即执行函数,并将i传入该函数即可。
6.对象拷贝与赋值
var foo={
name:'Tom',
age:25
}
var newfoo = foo;
newfoo.name = 'Lihua'
console.log(newfoo.name);//Lihua
console.log(foo.name);//Lihua
我们将foo对象赋值给了newfoo对象,从而改变newfoo的name属性,但是obj对象的name属性也被篡改,这是实际上newfoo获取对象是一个内存地址,并不是真正的拷贝,所以foo对象被篡改了。
var foo = {
name:'Mary',
age:25
}
var newfoo = Object.assign({},foo,{color:'blue'});
newfoo.name = 'Lihua'
console.log(newfoo.name);//Lihua
console.log(foo.name);//Mary
console.log(newfoo.color);//blue
利用Object.assign方法进行对象的深拷贝可以避免源对象被篡改的可能,因为Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
var foo = {
name:'Liming',
age:25
}
var newf = Object.create(foo);
newf.name="sun";
console.log(newf.name);//sun
console.log(foo.name);//Liming
我们也可以用Object,create来拷贝对象,Object.create可以创建一个具有原型对象和属性的新对象;
作为自己日常记录吧,借鉴别人的在此学习整理一下。 路漫漫兮其修远…
Console.assert();
在JavaScript程序的开发和维护过程中,Assert(断言)是一个很好的用于保证程序正确性的特性。在具备调试工具的浏览器上,这一特性可以通过调用console.assert()来实现。比如在以下代码中,console.assert()语句保证cat对象的score变量值长度为3:
function cat(name, age, score){
this.name = name;
this.age = age;
this.score = score;
}
var c = new cat("miao", 2, [6,8,7]);
console.assert(c.score.length==3, "Assertion of score length failed");
在console.assert()语句中,第一个参数为需要进行assert的结果,正常情况下应当为true;第二个参数则为出错时在控制台上打印的错误信息。比如,当上述例子中score变量的数组长度不为3时:
function cat(name, age, score){
this.name = name;
this.age = age;
this.score = score;
}
var c = new cat("miao", 2, [6,8]);
console.assert(c.score.length==3, "Assertion of score length failed");//因为c.score.length不等于3,所以输出错误语句。。
console.assert判断是否符合,如果不符合就输出错误信息…