<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>js知识点</title>
<style>
div{
width:100px;
height:100px;
background:red;
margin: 10px;
}
</style>
</head>
<body>
<div>0</div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
</body>
<script>
/**
* 变量作用域*/
//在函数中,声明并将a赋值,遵循就近原则输出a=2
var a = 1;
function test1() {
var a = 2;
alert(a);
}
//test1();
//在函数中作用域中声明并将a赋值,且在alert之下,a变量被提升,输出时已声明但未被赋值,所以输出undefined
var a = 1;
function test2() {
alert(a);
var a = 2;
}
//test2();
//函数作用域中a被重新赋值,未被重新声明,且位于alert之下,所以输出全局作用域中的a
var a = 1;
function test3() {
alert(a);
a = 2;
}
//test3();
//函数作用域中使用了ES6的let重新声明了变量b,而let不同于var其不存在变量提升的功能,所以输出报错b is not defined
let b = 1;
function test4() {
alert(b);
let b = 2;
}
//test4();
//函数作用域中用let声明了a为1,并在块级作用域中声明了a为2,因为alert并不在函数内的块级作用域中,所以输出1
function test5() {
let a = 1;
{
let a =2;
}
alert(a);
}
//test5();
/**
* 类型比较*/
//两个不同的数组比较,console为false
var arr = [];
arr2 = [1];
console.log(arr === arr2);
//两个相同的数组比较,因为两个单独的数组永不相等,console为false
var arr = [];
arr2 = [];
console.log(arr === arr2);
//利用typeof比较数组和对象,因为typeof获取NULL、数组、对象的类型都为object,所以console为true
var arr = [];
arr2 = {};
console.log(typeof (arr) === typeof (arr2));
//利用instanceof判断一个变量是否属于某个对象的实例,因为在JavaScript中数组也是对象的一种,所以两个console都为true
var arr = [];
console.log(arr instanceof Object);
console.log(arr instanceof Array);
/**
* this指向*/
//对象方法中的this指向对象本身,所以输出xiaoming
var obj = {
name:"xiaoming",
getName:function () {
return this.name;
}
}
console.log(obj.getName());
//对象中的方法赋值给了一个变量,此时方法中的this也将不再指向obj对象,从而指向window对象,所以console为undefined
var obj = {
myName:"xiaoming",
getName:function () {
return this.myName;
}
};
var nameFn = obj.getName;
console.log(nameFn());//注意这里的写法
//将obj对象中的方法赋值给了变量nameFn,但是通过apply方法将this指向了obj2对象,所以最终console为xiaohua
var obj = {
myName:"xiaoming",
getName:function () {
return this.myName;
}
};
var obj2 = {
myName:"xiaohua"
};
var nameFn = obj.getName;
console.log(nameFn.apply(obj2));
/**
* 函数参数*/
//利用函数中的arguments类数组对象获取传入函数的参数数组,所以输出数组[1, 2]
function test6() {
console.log(Array.prototype.slice.call(arguments)); //[1,2]
}
test6(1,2);
//利用arguments获取参数,但因test7(1, 2)未执行return中的函数,所以无输出。若执行test7(1, 2)(3, 4)则会输出[3, 4]
function test7() {
return function () {
console.log(Array.prototype.slice.call(arguments));
}
}
test7(1,2);
//利用Array.prototype.push.call()方法向args数组中插入了3和4,并利用ES6延展操作符(...)将数组展开并传入test9,所以console为[1, 2, 3, 4]
var args = [1,2];
function test9() {
console.log(Array.prototype.slice.call(arguments));
}
Array.prototype.push.call(args,3,4);
test9(...args);
/**
* 闭包*/
//点击任何div弹出的值总是5,因为当你触发点击事件的时候i的值早已是5
var elem = document.getElementsByTagName('div'); // 如果页面上有5个div
for(var i = 0; i < elem.length; i++) {
elem[i].onclick = function () {
alert(i); // 总是5
};
}
//使用闭包的方法解决
var elem = document.getElementsByTagName('div'); // 如果页面上有5个div
for(var i = 0; i < elem.length; i++) {
(function (w) {
elem[w].onclick = function () {
console.log(w); // 依次为0,1,2,3,4
};
})(i); //在点击事件外部封装一个立即执行的函数,并将i值传入该函数
}
/**
* 对象拷贝与赋值*/
//将obj对象赋值给了newObj对象,从而改变newObj的name属性,但是obj对象的name属性也被篡改,
// 这是因为实际上newObj对象获得的只是一个内存地址,而不是真正的拷贝,所以obj对象被篡改
var obj = {
name:"xiaoming",
age:23
};
var newObj = obj;
newObj.name = "xiaohua";
console.log(obj.name);
console.log(newObj.name);
//利用Object.assign()方法进行对象的深拷贝可以避免源对象被篡改的可能。
// 因为Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象
var obj2 = {
name: 'xiaoming',
age: 23
};
var newObj2 = Object.assign({}, obj2, {color: 'blue'});
newObj2.name = 'xiaohua';
console.log(obj2.name); // 'xiaoming'
console.log(newObj2.name); // 'xiaohua'
console.log(newObj2.color); // 'blue'
//也可以使用Object.create()方法进行对象的拷贝,Object.create()方法可以创建一个具有指定原型对象和属性的新对象
var obj3 = {
name: 'xiaoming',
age: 23
};
var newObj3 = Object.create(obj3);
newObj3.name = 'xiaohua';
console.log(obj3.name); // 'xiaoming'
console.log(newObj3.name); // 'xiaohua'
</script>
</html>
js问题知识点汇总
最新推荐文章于 2023-05-30 18:18:52 发布