当前位置: 首页 > news >正文

day22JS-对象静态方法

1. 创建对象的三种方法

  1. 用{}字面量创建:var 对象名 = {};
  2. 用new的方式创建:var 对象名 = new Object();
  3. 以什么对象为原型创建一个新对象:Object.create(对象名);

注意!!!

  • Object.create(对象名)方法的参数只能是对象或null。
  • 如果使用Object.create(null)作为原型创建对象,无属性,没有原型链,所以不能使用对象的任何方法。
  • Object.create(对象名)方法可以设置原型链。

 案例1:

    // 方法一:var o = {};// 方法二:var o = new Object();// 方法三: Object.create() 以什么对象为原型创建一个新对象var o = { a: 1, b: 2 };var o1 = Object.create(o);o1.c = 3;o1.d = 4;console.log(o1);

案例2:

    var o = Object.create(null);console.log(o);//无属性console.log(o + "1");//报错

案例3:

    var o1 = { a: 1 };var o2 = Object.create(o1);o2.b = 2;o2.z = 10;var o3 = Object.create(o2);o3.c = 3;o3.z = 100;var o4 = Object.create(o3);o4.d = 4;console.log(o4);

2. 对象属性

        对象属性分为对象属性原型属性。

        当获取对象属性时,首先查找对象的对象属性,如果没有则向下继续查找原型属性,找到最近的原型属性返回。

        当给对象设置属性时,不能设置原型属性只能设置对象的对象属性。原型对象的引用地址和对应的对象是一致。

案例1:

    var o1 = { a: 1 };var o2 = Object.create(o1);o2.b = 2;o2.z = 10;var o3 = Object.create(o2);o3.c = 3;o3.z = 100;var o4 = Object.create(o3);o4.d = 4;console.log(o4);// 对象属性中分为对象属性和原型属性// 当获取对象属性时,首先查找对象的对象属性,如果没有则向下继续查找原型属性,找到最近的原型属性返回console.log(o4.d);console.log(o4.b);console.log(o4.z);// 当给对象设置属性时,不能设置原型属性,只能设置对象的对象属性o4.z = 1000;console.log(o4);// 原型对象的引用地址和对应的对象是一致o3.z = 1;console.log(o4);

3. 获取原型链的方法

获取原型链的方法:

  1. 对象名.__proto__ :禁止使用__proto__
  2. Object.getPrototypeOf(对象名)

设置原型链的方法:

  1. 对象名.__proto__ = 对象名;:禁止使用__proto__
  2. Object.setPrototypeOf(目标对象, 作为原型链的对象);
  3. Object.create(对象名);

案例1: 

    var o1 = { a: 1 };var o2 = Object.create(o1);o2.b = 2;o2.z = 10;var o3 = Object.create(o2);o3.c = 3;o3.z = 100;var o4 = Object.create(o3);o4.d = 4;// 原型对象的引用地址和对应的对象是一致// 获取原型链  禁止使用__proto__console.log(o4.__proto__ === o3);// 获取原型链console.log(Object.getPrototypeOf(o4));

 案例2:

    var o1 = { a: 1 };var o2 = { b: 2 };// 禁止使用// o2.__proto__ = o1;// 设置原型链Object.setPrototypeOf(o2, o1);console.log(o2);

案例3: 使用两种方法让第一个对象{a:1}作为第二个对象{b:2}的原型,第二个对象{b:2}作为第三个对象 {c:3}的原型,形成原型链。

    // 方法一:var o1 = { a: 1 };var o2 = Object.create(o1);o2.b = 2;var o3 = Object.create(o2);o3.c = 3;console.log(o3);
-----------------------------------------------// 方法二:var o1 = { a: 1 };var o2 = { b: 2 };var o3 = { c: 3 };Object.setPrototypeOf(o2, o1);Object.setPrototypeOf(o3, o2);console.log(o3);

4. 迭代器和判断属性是否是当前对象的对象属性

遍历方法:

  1. for in 遍历:遍历对象时,可以遍历对象中的对象属性原型链属性不能遍历不可枚举属性。
  2. for of 遍历 :只能遍历迭代器。不能遍历对象。对象要使用for of必须使用迭代器。

判断这个属性是不是当前对象的对象属性的方法:

  1. Object.hasOwn(对象名,属性名):判断这个属性是不是当前对象的对象属性。

        Object.hasOwn(数组名,所以下标):判断数组的下标是不是空元素。

     2. 对象.hasOwnProperty(属性名) :判断这个属性是不是当前对象的对象属性。

迭代器:

  1. Object.entries(对象名):将对象转换为数组迭代器(二维数组)。例如:[["a",1],["b",2]]。
  2. Object.fromEntries(数组迭代器) :将数组迭代器(二维数组)转换为对象

案例1:

    var o1 = { a: 1 };var o2 = { b: 2 };var o3 = { c: 3 };Object.setPrototypeOf(o2, o1);Object.setPrototypeOf(o3, o2);// 遍历对象时,可以遍历对象中的对象属性和原型链属性,不能遍历不可枚举属性// Object.hasOwn(对象,属性)判断这个属性是不是当前对象的对象属性// 对象.hasOwnProperty(属性) 判断这个属性是不是当前对象的对象属性for (var key in o3) {console.log(key);console.log(key, Object.hasOwn(o3, key));console.log(o3.hasOwnProperty(key));}

案例2:

    var arr = ["a", "b", , "c"];// Object.hasOwn(数组,下标)判断数组的下标是不是空元素console.log(Object.hasOwn(arr, 2));console.log(arr.hasOwnProperty(2));

案例3:

    var o = { a: 1, b: 2, c: 3 };console.log(Object.entries(o));// [["a",1],["b",2],["c",3]]// 对象不是迭代器,本身不能使用for offor (var [key, value] of Object.entries(o)) {console.log(key, value);}

案例4:

    // 将迭代器转换为对象var o = Object.fromEntries([["a", 1], ["b", 2]])console.log(o);

 5. 对象浅复制

 Object.assign(目标对象,...源对象) :将源对象中所有可枚举的对象属性复制到目标对象的对象属性上,如果源对象中的属性有重复,后面的会覆盖前面的源对象可以是多个。 这个方法最后返回目标对象

 案例1:

    var o = { a: 1, b: 2 };var o1 = Object.create(o);o1.c = 3;o1.d = 4;var o2 = { e: 4, f: 5 };Object.assign(o2, o1);console.log(o2);

案例2:

    var o1 = { a: 1 };var o2 = { b: 2, z: 1 };var o3 = { c: 3, z: 2 };var o4 = { d: 4 };Object.assign(o4, o1, o2, o3)console.log(o4);

案例3:

    var o1 = { a: 1 };var o2 = { b: 2 };var o3 = Object.assign({}, o1, o2);console.log(o3);// {...}这种写法一般用于创建一个新对象// Object.assign() 用于已有对象复制使用var o4 = { ...o1, ...o2 };console.log(o4);

 6. 冻结、密封、禁止扩展对象

  1. Object.freeze(对象名):冻结对象。对象不能删除属性,不能添加新属性,不能修改属性值。在js中没有enum枚举所以使用该方法可以属性enum 枚举。
  2. Object.isFrozen(对象名):当前对象是否被冻结。

  1. Object.seal(对象名): 密封对象,可以修改属性,但是不能删除和添加新属性。
  2. Object.isSealed(对象名):判断是否被密封。

  1. Object.preventExtensions(对象名) : 禁止扩展对象,可以删除属性,可以修改属性,但是不能添加新属性。
  2. Object.isExtensible(对象名) : 判断是否被禁止扩展对象。false代表禁止扩展, true表示可扩展。

案例1:

    // 冻结对象 对象不能删除属性,不能添加新属性,不能修改属性值var o = { a: 1, b: 2 };Object.freeze(o)// 删除对象属性delete o.a;console.log(o);// 修改对象属性o.a = 10;console.log(o);// 添加对象属性o.c = 10;console.log(o);

案例2:

    const COLOR = Object.freeze({ RED: "RED", BLUE: "BLUE", YELLOW: "YELLOW", GREEN: "GREEN" })// 当前对象是否被冻结console.log(Object.isFrozen(COLOR));//true

案例3:

    var o1 = Object.seal({ a: 1, b: 2 })o1.a = 10;console.log(o1);// 判断是否被密封console.log(Object.isSealed(o1));

案例4:

    // 禁止扩展 可以删除属性,可以修改属性,但是不能添加新属性var o1 = Object.preventExtensions({ a: 1, b: 2 })delete o1.a;o1.b = 10;o1.c = 20;console.log(o1);// false代表禁止扩展 true表示可扩展console.log(Object.isExtensible(o1));

7. 添加属性并定义该属性特性的方法

1. Object.defineProperty(对象, "属性名", 属性描述对象) :定义单个属性。该方法不能删除,在严格模式下,删除会报错;不能重新定义;属性定义为不可枚举时for in是不能遍历到该属性的,但能拿到该属性的值;当该属性定义为不可修改时,该属性不能修改,如果在严格模式下,删除会报错。

属性描述对象中的属性:

  • enumerable:是否可枚举。布尔值。
  • configurable: 是否可删除或者重新设置属性描述对象。布尔值。
  • writable:是否可写,是否可以修改。布尔值。
  • value : 如果value是非函数,则这是一个属性值,如果value是一个函数,则这是一个方法。value:function(){...}或value(){...}都表示value是一个函数。

该方法的使用模板1:

    Object.defineProperty(对象名, "属性名", {

      enumerable: true,

      configurable: true,

      writable: true,

      value: 属性值,

    })

该方法的使用模板2:

    Object.defineProperty(对象名, "属性名",{

      enumerable: true,

      configurable: true,

      set(value) {

      },

      get() {

      }

    })

特性写法:这个写法默认该属性不可删除,不可修改,不可枚举

    Object.defineProperty(对象名, "属性名", {

      // 默认如果不写则为false

      value: 属性值

    })

2. Object.defineProperties(对象,对象多属性描述对象):定义多个属性。

该方法使用模板:

    Object.defineProperties(对象名, {

      // 属性名:属性描述对象

      a: {

        enumerable: true,

        configurable: true,

        writable: false,

        value: 1

      },

      b: {

        value: 2

      }

    })

案例1:

    // 属性var o = { a: 1, b: 2 };Object.defineProperty(o, "c", {enumerable: true,configurable: true,writable: true,value: 3,})console.log(o);

案例2: 

    var o = { a: 1, b: 2 };Object.defineProperty(o, "play", {enumerable: true,configurable: true,writable: true,// value:function(){}value() {console.log("play");}})console.log(o);

案例3:

    var o = { a: 1, b: 2 };Object.defineProperty(o, "c", {configurable: false,writable: true,enumerable: true,value: 3})// 不能删除delete o.c;console.log(o);// 不能重新定义Object.defineProperty(o, "c", {//报错configurable: true,writable: true,enumerable: true,value: 3})console.log(o);

案例4:属性c不能被遍历出来。

    var o = { a: 1, b: 2 };Object.defineProperty(o, "c", {configurable: true,enumerable: false,//不可枚举writable: true,value: 3})console.log(o);for (var key in o) {console.log(key);}

 案例5:

    var o = { a: 1, b: 2 };Object.defineProperty(o, "c", {configurable: true,enumerable: true,writable: false,//不可修改,不可写value: 3})o.c = 10;console.log(o.c);//3

案例6:定义多个属性

    var o = {};Object.defineProperties(o, {// 属性名:属性描述对象a: {enumerable: true,configurable: true,writable: false,value: 1},b: {value: 2}})console.log(o);

 案例7:

    var o = {a: 1,"b-1": 2,[Symbol("a")]: 3}Object.defineProperties(o, {c: {value: 4},[Symbol("b")]: {writable: true,value: 5}})console.log(o);

8. 遍历不可枚举属性的方法

for in遍历:不靠谱,只能遍历可枚举,并且只能是字符的串属性名。

  1. Object.getOwnPropertyNames(对象名) :获取对象的所有可枚举和不可枚举的字符串属性名。
  2. Object.getOwnPropertySymbols(对象名):获取对象的所有可枚举和不可枚举的Symbol属性名。
  3. Reflect.ownKeys(对象名): Reflect 针对Object对象的所有方法反射方法集,获取到对象中所有的可枚举和不可枚举的任意类型属性名。

案例1:

    var o = {a: 1,"b-1": 2,[Symbol("a")]: 3}Object.defineProperties(o, {c: {value: 4},[Symbol("b")]: {writable: true,value: 5}})console.log(o);// 不靠谱 只能遍历可枚举,并且字符串属性名// for (var key in o) {//   console.log(key, o[key]);// }// 获取对象的所有可枚举和不可枚举的字符串属性名var arr = Object.getOwnPropertyNames(o);// 获取对象的所有可枚举和不可枚举的Symbol属性名var arr1 = Object.getOwnPropertySymbols(o);console.log(arr, arr1);

案例2:遍历

    var o = {a: 1,"b-1": 2,[Symbol("a")]: 3}Object.defineProperties(o, {c: {value: 4},[Symbol("b")]: {writable: true,value: 5}})console.log(o);// 合并写法一;var arr = Object.getOwnPropertyNames(o).concat(Object.getOwnPropertySymbols(o))for (var i = 0; i < arr.length; i++) {console.log(arr[i], o[arr[i]]);}-----------------------------------------------------------------------------------------var o = {a: 1,"b-1": 2,[Symbol("a")]: 3}Object.defineProperties(o, {c: {value: 4},[Symbol("b")]: {writable: true,value: 5}})console.log(o);// 合并写法二;var arr = [...Object.getOwnPropertyNames(o), ...Object.getOwnPropertySymbols(o)]for (var i = 0; i < arr.length; i++) {console.log(arr[i], o[arr[i]]);}
-----------------------------------------------------------------------------------------var o = {a: 1,"b-1": 2,[Symbol("a")]: 3}Object.defineProperties(o, {c: {value: 4},[Symbol("b")]: {writable: true,value: 5}})console.log(o);// 获取到对象中所有的可枚举和不可枚举的任意类型属性名// Reflect 针对Object对象的所有方法反射方法集var arr = Reflect.ownKeys(o);for (var i = 0; i < arr.length; i++) {console.log(arr[i], o[arr[i]]);}

 

9. 获取对象属性的描述对象

  1. Object.getOwnPropertyDescriptor(对象名, "属性名") :获取对象属性的描述对象。
  2. Object.getOwnPropertyDescriptors(对象名) : 获取对象属性上所有的描述对象。

案例1:

    var o = {a: 1,"b-1": 2,[Symbol("a")]: 3}Object.defineProperties(o, {c: {value: 4},[Symbol("b")]: {writable: true,value: 5}})// 获取对象属性的描述对象var desc = Object.getOwnPropertyDescriptor(o, "c");console.log(desc);

 案例2:

    var o = {a: 1,"b-1": 2,[Symbol("a")]: 3}Object.defineProperties(o, {c: {value: 4},[Symbol("b")]: {writable: true,value: 5}})// 获取对象属性上所有的描述对象var descs = Object.getOwnPropertyDescriptors(o);console.log(descs);

 10. 对象群组方法

Object.groupBy( 数组迭代器, function (元素, 索引下标) { }):遍历或分组。返回的是数组。

案例1:

   var o = { a: 1, b: 2 };Object.groupBy(Object.entries(o), function (item, index) {console.log(item, index);})

案例2:

    var arr = ["a", "b", "c"];Object.groupBy(arr, function (item, index) {console.log(item, index);})

 案例3:

    var list = [{ a: 1, type: 0, price: 1000 },{ a: 2, type: 1, price: 2000 },{ a: 3, type: 0, price: 2000 },{ a: 4, type: 1, price: 3000 },{ a: 5, type: 1, price: 4000 },{ a: 6, type: 0, price: 5000 },]var list1 = Object.groupBy(list, (item) => item.type);console.log(list1);

 

11. isNaN()、Number.isNaN()和Object.is()的区别

  1. isNaN() :该方法会隐式转化,在判断是不是NaN。
  2. Number.isNaN():该方法直接判断NaN。不会隐式转化。
  3. Object.is():该方法是判断两个值是否绝对相等(===),不会隐式转化。能判断与NaN是否绝对相等(===)。

 案例1:

    // isNaN()// Number.isNaN()不会隐式转换// Object.is()  与===相类似  判断是否绝对相等var a = 1;var b = "1";console.log(Object.is(a, b));//false// ===永远不等于NaNconsole.log(Number("a") === NaN);console.log(Object.is("a", NaN)); 

12. 获取对象key-valus的方法

Object.keys(对象名) :只能获取到对象中所有可枚举的字符串属性名组成数组。

Object.values(对象名) :只能获取到对象中所有可枚举的字符串属性名对应属性值组成数组。

 案例:

    var obj = { a: 1, b: 2, c: 3 };// 只能获取到对象中所有可枚举的字符串属性名组成数组console.log(Object.keys(obj));// 只能获取到对象中所有可枚举的字符串属性名对应属性值组成数组console.log(Object.values(obj));

 13. 对象的getter和setter

 getter和setter是访问器属性。

希望可以像属性一样使用=号赋值,并且在赋值后还可以执行多条语句。

案例:本案例中,怎么做到重新执行 obj.init();就能到达重新渲染页面的效果。

        var obj = {list: [1, 2, 3, 4],init() {document.body.innerHTML = `<ul>${this.list.reduce((v, t) => v + `<li>${t}</li>`, "")}</ul>`}}obj.init();//怎么做到重新执行 obj.init();就能到达重新渲染页面的效果obj.list = ["a", "b", "c", "d"]obj.init();

解决方法:定义对象时,直接加入set和get方法。

  1. set 方法:有且仅有一个参数,并且不允许使用return返回任何值;当赋值时,执行set这个方法,参数就是赋值的结果,可以在赋值后执行多条语句;如果只写set 不写get,表示这个属性只能设置值,不能获取该属性,是只写属性
  2.  get 方法:不能有参数,并且必须return返回一个值;获取对象属性 时,执行get方法,获取最后要有一个获取的结果,所以需要return结果;如果只写get 不写set,表示这个属性只能获取值,不能设置改变值 ,是只读属性;这个get这个属性不能用来存储任何内容,需要借助第三方属性存储。

 案例1:

        // 定义对象时,直接加入set和getvar obj = {_list: 1,// set 方法 有且仅有一个参数,并且不允许使用return返回任何值// list 这个getset属性不能用来存储任何内容,需要借助第三方属性存储set list(value) {this._list = value;// console.log("set",value);},// get 方法 不能有参数,并且必须return返回一个值get list() {// console.log("get");// return ""return this._list;}}// 和属性的赋值方法完全相同// 当赋值时,执行set list这个方法,参数就是赋值的结果,可以在赋值后执行多条语句// 如果只写set 不写get,表示这个属性只能设置值,不能获取该属性  只写obj.list = "a";// 获取对象属性  执行get list方法,获取最后要有一个获取的结果,所以需要return结果// 如果只写get 不写set,表示这个属性只能获取值,不能设置改变值  只读console.log(obj.list);

案例2:

        var obj = {_list: [],// 重新给属性赋值时才会执行setset list(value) {if (!Array.isArray(value)) return;this._list = value;document.body.innerHTML = `<ul>${this.list.reduce((v, t) => v + `<li>${t}</li>`, "")}</ul>`},get list() {return this._list;}}obj.list = [1, 2, 3, 4]document.addEventListener("click", () => {obj.list = ["a", "b", "c", "d", "e"]// obj.list.push(5);obj.list = obj.list.concat(5);})

 案例3:div自动移动案例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div {width: 50px;height: 50px;background-color: red;position: absolute;left: 0;top: 0;}</style>
</head><body><div></div><script type="module">var div = document.querySelector("div");var obj = {_x: 0,_y: 0,set x(value) {this._x = value;div.style.left = value + "px";},get x() {return this._x},set y(value) {this._y = value;div.style.top = value + "px";},get y() {return this._y;}}setInterval(() => {//               set   getobj.x++;//相当于obj.x=obj.x+1obj.y++;}, 16)</script>
</body></html>

案例4:div自动移动案例的升级版

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div {width: 50px;height: 50px;background-color: red;position: absolute;left: 0;top: 0;}</style>
</head><body><div></div><script type="module">var div = document.querySelector("div");// 如果对象已经存在,如果要给对象中添加setget属性,就必须使用defineProperty或者definePropertiesHTMLElement.prototype.a = 10;console.log(div.a);Object.defineProperties(HTMLElement.prototype, {_x: {writable: true,//可修改,不可枚举,不可删除value: 0},_y: {writable: true,//可修改,不可枚举,不可删除value: 0},x: {set(value) {this._x = value;this.style.left = value + "px"},get() {return this._x;}},y: {set(value) {this._y = value;this.style.top = value + "px"},get() {return this._y;}}})setInterval(() => {div.x++;div.y++;}, 16)</script>
</body></html>

14. 对象深复制

14.1 对象浅复制的弊端

复制对象的目的,修改对象后,不会引起源对象的改变,保留源对象的内容。

  1. JSON.stringify(对象名) :将对象转换为JSON格式的字符串。格式  '{"属性名":属性值}'。 属性值如果是字符串需要使用""。
  2. JSON.parse():把JSON格式的字符串转换为对象,返回新对象;可以用于把字符串强转为布尔类型和数值类型。

案例:将下面对象的age属性进行随机修改,修改范围在25<x<35的范围内就停止修改。

        var data = {name: "xietian",age: 30,sex: "男"}

解决方法:下面的方法都是浅复制

        var data = {name: "xietian",age: 30,sex: "男"}while (1) {// 复制对象方法一:// var newData = {}// for (var key in data) {//     newData[key] = data[key]// }// 复制对象方法二:// var newData = Object.assign({}, data);// var newData = { ...data };// 复制对象方法三:var newData = Object.keys(data).reduce((v, k) => v[k] = data[k], {})newData.age = ~~(Math.random() * 100)if (newData.age < data.age + 5 && newData.age > data.age - 5) {break;}}console.log(newData);

浅复制只能复制一层,遇到对象中属性值还是对象的,改变复制新对象的属性,还是会改变源对象的属性值。属性值的引用地址没有变。例如:如下图所示:

        var data = {a: 1,b: {c: 2}}

 为了解决上述问题,使用要使用深复制。

14.2 对象深复制使用

14.2.1 方法一:使用lodash插件可以进行对象深复制

lodash插件的方法:

 _.cloneDeep(对象名) :深复制

1. 下载lodash插件,打开集成终端输入npm i lodash

2. 创建一个js的文件夹,在node_modules下把lodash.js放在js文件夹下,删除node_modules。

3. 在页面中引入lodash插件。

<script src="./js/lodash.js"></script>

4. 编写代码

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./js/lodash.js"></script>
</head><body><script>var data = {a: 1,[Symbol("a")]: 2,c: /a/g,b: {c: 3,play() {console.log("aa");}}}//深复制方法一:// var newData = JSON.parse(JSON.stringify(data));// console.log(newData);//深复制方法二:var newData = _.cloneDeep(data);// 改变源对象的值,查看是否会改变新对象的值data.b.c = 30;console.log(newData, data);</script>
</body></html>

 lodash插件进行深复制也有弊端,有些数据还有引用关系。

14.2.2 方法二:封装对象深复制(重点)

遍历分为 广度遍历(  for ,for in ,for of)和 深度遍历( while ,递归)

1. 怎样做递归?递归的方式分两种。

  • 方法一:先做深度遍历,在做广度遍历。
  • 方法二:先做广度遍历,在做深度遍历。

案例1:二叉树的遍历

    var tree = {value: 1,left: {value: 2,left: {value: 4,left: null,right: null},right: {value: 5,left: null,right: null},},right: {value: 3,left: {value: 6,left: null,right: null},right: {value: 7,left: null,right: null},},};// 先序遍历// function showTree(tree) {//   console.log(tree.value);//   if (tree.left) showTree(tree.left)//   if (tree.right) showTree(tree.right)// }// 中序遍历// function showTree(tree) {//   if (tree.left) showTree(tree.left)//   console.log(tree.value);//   if (tree.right) showTree(tree.right)// }// 后序遍历function showTree(tree) {if (tree.left) showTree(tree.left)if (tree.right) showTree(tree.right)console.log(tree.value);}showTree(tree);

案例2:

    var obj = {a: 1,b: {c: [1, 2, 3, 4],d: {e: 3,},},f: {g: {h: 4,},},};//方法一:先做深度遍历,在做广度遍历。// function showDeep(obj) {//   for (var key in obj) {//     // 是对象,但不是null//     if (obj[key] && typeof obj[key] === "object") {//       showDeep(obj[key])//     } else {//       console.log(obj[key]);//     }//   }// }// 方法二:先做广度遍历,在做深度遍历。function showDeep(obj) {if (typeof obj !== "object" || !obj) {console.log(obj);}for (var key in obj) {showDeep(obj[key])}}showDeep(obj);

 案例3:尾递归 ,在尾部递归。

    // 递归  尾递归  在尾部递归var i = 0;var sum = 0;function getSum() {i++;if (i > 100) return;sum += i;getSum();}getSum();console.log(sum);

案例4:

 


http://www.mrgr.cn/news/29518.html

相关文章:

  • 如何编写可维护的代码:最佳实践与技巧
  • 克隆centos网卡uuid相同如何修改
  • 进程的重要函数
  • 基于树表的查找
  • 网络封装分用
  • OpenHarmony(鸿蒙南向开发)——标准系统方案之瑞芯微RK3568移植案例(下)
  • 伪工厂模式制造敌人
  • 喜报!亲笔签数字科技荣获2024年“数据要素X”大赛重庆分赛三等奖
  • 构建 LLM 应用程序时经常遇到的高级概念的快速指南
  • 3.postman脚本语言、接口关联(json引用(变量)、脚本用正则表达式)、断言封装、自动化构造接口请求(Postman工具)
  • 直播开播极速流,如何有效接入?
  • 基于Spring Boot的学生社区故障维修预约系统的设计与实现(开题报告)
  • C++面试模拟01
  • C++:日期类的实现
  • YOLOv8改进:SA注意力机制【注意力系列篇】(附详细的修改步骤,以及代码,与其他一些注意力机制相比,不仅准确度更高,而且模型更加轻量化。)
  • 隐藏excel单元格数据的两个方法
  • 【d2l安装超详细老妈子教程】
  • 史上最强异步编程~CompletableFuture精读
  • hym8563/pcf8563 定时关机后,中断没有清除,导致INT脚一直为低,系统不开机。
  • GEE教程:1950-2023年ECMWF数据中积雪的长时序统计分析