欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

细说(值传递、引用传递)的区别, 数组和对象解构的常用方法, call.apply.bind的区别与联系, 访问器属性的原理与实现

程序员文章站 2022-02-17 11:28:34
...

值传递与引用传递的区别与联系:

  1. 深拷贝:
  2. 值传递: 原始类型,string,number,bool
  3. 引用传递: 引用类型,object,array
  4. 浅拷贝: 引用传递
  5. 入参:调用函数是传入的参数,简称:"入参"

样式代码:

  1. <script>
  2. let a = 1; //赋值、值传递:原始类型,string,number,bool
  3. console.log("a = %d, b = %d", a, b);
  4. a = 2;
  5. console.log("a = %d, b = %d", a, b); //更新a,不影响b
  6. let obj1 = { a: 1, b: 2 }; //引用传递:引用类型,object,array
  7. console.log(obj1);
  8. let obj2 = obj1;
  9. console.log(obj2);
  10. obj1.a = 10; // 更新obj1
  11. console.log(obj1);
  12. console.log(obj2); //obj2同步更新
  13. const f1 = (x) => (x = 10); //传参时,不论什么类型,都是"值传递"
  14. let m = 5;
  15. console.log("m = %d", m);
  16. f1(m);
  17. console.log("m = %d", m); //函数中对参数的更新,并不会影响到入参
  18. const f2 = (x) => (x.a = 10);
  19. let o = { a: 1, b: 2 };
  20. console.log(o);
  21. f2(o);
  22. console.log(o); //看上去函数中对于o.a的更新生效,实际上仍是值传递
  23. const obj = { x: 1, y: 2 }; //对于引用类型,只有全新赋值才算是更新,修改属性不算的
  24. obj.x = 20;
  25. const f3 = (x) => (x = {}); // 赋值一个全新对象,才是更新
  26. f3(o);
  27. console.log(o); // 函数中对于对象/引用参数的更新并没有影响到入参
  28. </script>

效果预览:

细说(值传递、引用传递)的区别, 数组和对象解构的常用方法, call.apply.bind的区别与联系, 访问器属性的原理与实现

数组和对象解构的常用方法与函数传数:

  1. 解构赋值: 快速从集合数据(数组/对象解构出独立变量)
  1. <script>
  2. let [a, b, c] = [1, 2, 3]; //数组
  3. console.log(a, b, c);
  4. [a, b] = [1, 2, 3];
  5. console.log(a, b);
  6. [a, b, c, d = "xxxx"] = [1, 2, 3];
  7. console.log(a, b, c, d);
  8. [a, b, ...c] = [1, 2, 3, 4, 5];
  9. console.log(a, b, c);
  10. [, , a, ,] = [1, 2, 3, 4, 5];
  11. console.log(a);
  12. let x = 1,
  13. y = 2,
  14. t;
  15. console.log("x = %d, y = %d", x, y);
  16. [y, x] = [x, y];
  17. console.log("x = %d, y = %d", x, y);
  18. let { id, name } = { id: 10, name: "手机" }; //对象解构
  19. console.log(id, name);
  20. ({ name, id } = { id: 10, name: "手机" }); //属性名与变量名必须一一对应,顺序无所谓
  21. console.log(id, name);
  22. let email = "admin@php.cn";
  23. let { role, email: userEmail } = { role: "user", email: "user@php.cn" };
  24. console.log(userEmail);
  25. console.log(email);
  26. //参数解构
  27. let sum = ([a, b]) => a + b; //数组传参
  28. console.log(sum([10, 20]));
  29. let getUser = ({ name, email }) => [name,email]; // 对象传参
  30. console.log(getUser({ email: "tp@php.cn", name: "老师" }));
  31. </script>

效果预览:

细说(值传递、引用传递)的区别, 数组和对象解构的常用方法, call.apply.bind的区别与联系, 访问器属性的原理与实现

bind,call,apply的区别与联系:

  1. bind()不会立即执行,只返回一个函数声明
  2. call/apply立即执行

样式代码:

  1. <body>
  2. <button>click</button>
  3. <script>
  4. function hello(name) {
  5. this.name = name;
  6. console.log(this.name);
  7. }
  8. const obj = { name: "admin" };
  9. //经典调用
  10. console.log(hello("朱老师"));
  11. //bind()不会立即执行
  12. let f = hello.bind(obj, "天蓬老师");
  13. console.log(f());
  14. //call/apply立即执行
  15. f = hello.call(obj, "灭绝老师");
  16. console.log(f);
  17. f = hello.apply(obj, ["西门老师"]);
  18. console.log(f);
  19. </script>
  20. </body>

效果预览:

细说(值传递、引用传递)的区别, 数组和对象解构的常用方法, call.apply.bind的区别与联系, 访问器属性的原理与实现

访问器属性的原理与实现过程:

  1. 将方法伪造成一个属性

样式代码:

  1. <script>
  2. const product = {
  3. data: [
  4. { name: "电脑", price: 5000, num: 5 },
  5. { name: "手机", price: 4000, num: 10 },
  6. { name: "电视", price: 9000, num: 4 },
  7. ],
  8. get total() { // 将方法伪造成一个属性
  9. return this.data.reduce((t, c) => (t += c.price * c.num), 0);
  10. },
  11. set setPrice(price) {
  12. this.data[1].price = price;
  13. },
  14. };
  15. console.log("总金额 :", product.total);
  16. console.log(product.data[1].price);
  17. product.setPrice = 9988;
  18. console.log(product.data[1].price);
  19. </script>

细说(值传递、引用传递)的区别, 数组和对象解构的常用方法, call.apply.bind的区别与联系, 访问器属性的原理与实现

访问器属性的优先级:

  1. 访问器属性优先级高于同名的普通属性
  1. <script>
  2. let user = {
  3. data: { name },
  4. get name() {
  5. return this.data.name;
  6. },
  7. set name(value) {
  8. this.data.name = value;
  9. },
  10. };
  11. user.name = "今天天气真不错";
  12. console.log(user.name);
  13. </script>

多分支与swithc转换的技巧:

  1. score = 90; //多分支
  2. if (score >= 60 && score < 80) {
  3. console.log("合格");
  4. } else if (score >= 80 && score <= 100) {
  5. console.log("学霸");
  6. }
  7. else if (score > 100 || score < 0) { // 判断成绩是否合法
  8. console.log("非法数据");
  9. } else {
  10. console.log("补考吧");
  11. }
  12. score = 90; //switch来简化多分支时,switch是严格匹配
  13. switch (true) {
  14. case score >= 60 && score < 80:
  15. console.log("合格");
  16. break;
  17. case score >= 80 && score <= 100:
  18. console.log("学霸");
  19. break;
  20. case score > 100 || score < 0: //判断成绩是否合法
  21. console.log("非法数据");
  22. break;
  23. default:
  24. console.log("补考吧");
  25. }
  26. let response = "Success"; // switch用在单值判断
  27. switch (response.toLocaleLowerCase()) {
  28. case "fail":
  29. console.log("请求失败");
  30. break;
  31. case "success":
  32. console.log("请求成功");
  33. break;
  34. default:
  35. console.log("未知错误");
  36. }
  37. </script>

效果预览:

细说(值传递、引用传递)的区别, 数组和对象解构的常用方法, call.apply.bind的区别与联系, 访问器属性的原理与实现

三元运算符:

  1. 简化双分支:条件? true : false
  2. 如果为真执行第一个分支,
  3. 如果为假执行第二个分支,
  4. 三元运算符会将:右边的视为一个整体,其优先级应该是很低的,如果要先求三元运算符中的顺,必须先将其用括号括起来:
  1. <script>
  2. //双分支
  3. score = 60;
  4. console.log(score >= 60 ? "及格" : "补考吧");
  5. </script>