解析:
值传递:通常用于原始类型数据的赋值,如string,number,bool
引用传递:通常用于引用类型数据的赋值,如object,array
值传递代码说明:
let a=2;
let b=a; //将a的值赋给b
console.log("a=%d,b=%d",a,b); //控制台输出 a=2,b=2
a=3;
console.log("a=%d,b=%d",a,b); //控制台输出 a=3,b=2
注: 原始类型的a发生改变,不影响b的值
值传递代码说明:
let obj1={a:1,b:2};
let obj2=obj1;
//以下现行代码都在控制台输出{a:1,b:2}
console.log(obj1);
console.log(obj2);
//更新obj1
obj1.a =10;
console.log(obj1); //控制台输出{a:10,b:2}
console.log(obj2); //控制台输出{a:10,b:2}
区别与联系:
值传递传递的是内存中存放的数据,把a的值赋给b,两个之间没有任何联系。
引用传递传递的是内存的地址,把a的值赋给b,相当于a和b指向同一个内存地址,当时内存地址中存放的数据发生改变,则a和b的值都会同步发生改变。
解析:解构赋值,目的是快速从集合数据(数组和对象)解构出独立变量,其实相当于给集合数据中的每个数据指定成一组key/value名值对。通过key就能快速的访问到value值。
通过设定好的key(a,b,c),就能访问到对应的value
数量一致
let [a,b,c] = [1,2,3];
console.log(a,b,c);//控制台输出1,2,3
key值多,那没有对应value值的key就会显示为undefined
let [a,b,c,d] = [1,2,3];
console.log(a,b,c,d);//控制台输出1,2,3,undefined
//可以指定默认值的方式给上面的d赋值
let [a,b,c,d=10] = [1,2,3];
console.log(a,b,c,d);//控制台输出1,2,3,10
如果key值数量比数组长度小,那么按照顺序对应
let [a,b] = [1,2,3];
console.log(a,b);//控制台输出1,2,数组中的3没有对应的key
如果想直接访问到数组的特定位置的value,如第三个,则前面两个可以用 , 来占位
let [,,c] = [1,2,3];
console.log(c);//控制台输出3
对象解构前提:属性名与变量名必须一一对应,顺序无所谓
let {id,name,email} = {id:1,name="T-Mac",email="123@abc.com"}
console.log(id,name,email);//输出:1,T-Mac,123@abc.com
当变量已经存在时,同名的属性名有可能会将已存在的变量覆盖,造成数据流失,此时可以通过起别名的方式来避免冲突。
let email="456@abc.com";
let {id,name,email} = {id:1,name="T-Mac",email="123@abc.com"}
console.log(email);//控制台输出123@abc.com,因为覆盖造成456@abc.com数据流失
起别名:
let email="456@abc.com";
let {id,name,email:'Temail'} = {id:1,name="T-Mac",email="123@abc.com"}
console.log(Temail);//控制台输出123@abc.com
console.log(email);//控制台输出456@abc.com
call,apply,bind方法主要用来动态改变this指向的对象
以下代码是页面上的给页面上的button控件添加一下点击事件,正常情况下控制台上输出的name应该是空,因为button并没有指定name属性,此时this指向对象是button
<button>click</button>
//以下是script代码
document.querySelector("button").addEventListener(
"click",function(){
console.log(this.name);
console.log(this);
}
);
应用bind()改写如下,此时this不再指向button,而是指向我们通过bind()方法传入的对象{name:”人与自然”}
document.querySelector("button").addEventListener(
"click",function(){
console.log(this.name);
console.log(this);
}.bind({name:"人与自然"})
);
bind()只返回一个函数声明,不会立即执行,与之不同的是call()和apply()会立即执行
公共代码:
function hello(name){
this.name = name ;
console.log(this.name);
}
const obj = {
name:"admin",
};
//经典调用
console.log(hello("朱老师")); //控制台输出朱老师,里面的this指定hello("朱老师")
//将hello绑定到obj对象中,bind()不会马上执行,只返回一个函数声明,此时this指向被更改,指向obj对象{"天蓬老师"},
let f = hello.bind(obj,"天蓬老师");
console.log(f); //控制台输出f函数的源代码
console.log(f());//此时f函数才会调用,输出"天蓬老师"
//call/apply立即执行
f = hello.call(obj,'灭绝师太');
console.log(f); //正常函数时,此时控制台应该输出函数源代码,但是由于call/apply函数的特性,此时控制台已经直接输出:灭绝师太
call()和apply的区别在于参数类型不同,后面那个参数必须是一个数组
上面代码应用apply()改成如下:
f = hello.apply(obj,['灭绝师太']);
console.log(f); //正常函数时,此时控制台应该输出函数源代码,但是由于call/apply函数的特性(会立即执行),此时控制台已经直接输出:灭绝师太
访问器属性本质是对象里面定义的一个方法,但是可以伪装成对象的一个属性来使用。实际使用时,应该以性情赋值的方式,不能以调用方法的格式。
示范代码:
const product = {
data [
{name = "电脑",price : 5000, num: 5},
{name = "手机",price : 4000, num: 10},
{name = "相机",price : 10000, num: 3},
]
//定义一个访问器属性(一个set方法)
set setPrice(price){
this.data[1].price = price ;
}
};
////错误,控制台提示:product.setPrice is not a function。因为setPrice是一个访问器属性,不能以调用方法的形式 setPrice(9999)进行调用,面应该以属性赋值的方式来进行调用
//product.setPrice(9999); //错误代码
product.setPrice = 9999;
console.log(product.data[1].price);//控制台输出9999
另外,这种访问器属性一旦与对象原有属性重名时,会存在优先级的问题。
let user = {
name = "张无忌";
//访问器属性name()与原有属性name重名
get name(){
return "杨过";
}
};
console.log(user.name); //控制台输出 杨过
以上代码可以看出,当访问器属性与对象的原有属性重名时,访问器属性的优先级较高,但是尽量不要出现访问器属性与原有属性重名的情况。
多分支一般用于多元判断,最简单的应用就是分数评级,如
let score = 65;
if( score < 60 ){
console.log("不及格");
} else if ( score >= 60 && score <80 ){
console.log("及格且良好");
}else if ( score >= 80 && score <=100 ){
console.log("优秀");
}
//最终控制台输出及格且良好
if-else if -else 可以用于区间判断,但是switch只能用于严格匹配
let response = "success";
switch (response.toLowerCase()){
case "fail" :
console.log("请求失败");
break;
case "success" :
console.log("请求成功");
break;
default:
console.log("未知错误");
//默认分支后面不用添加break;
}
三元运算一般用来解决双分支问题,非黑即白。如果条件判断为真,返回结果1,否则返回结果2
格式为: 条件判断?结果1 : 结果2;
示范代码:
console.log(score>60?"及格" : "不及格");