JS链式调用、对象属性与遍历、this指向

360 阅读4分钟

链式调用、对象属性与遍历、this指向、caller、callee

链式调用

 let sched = {
   wekeup: function () {
     console.log("Running");
     return this;
   },
   morning: function () {
     console.log("Going shopping");
     return this;
   },
   noon: function () {
     console.log("Having a rest");
     return this;
   },
   afternoon: function () {
     console.log("Studying");
     return this;
   },
   evening: function () {
     console.log("Walking");
     return this;
   },
   night: function () {
     console.log("Sleeping");
     return this;
   },
 };
     
 sched.wakeup().morning().noon().afternoon().evening().night();
 ​
  • 必须要返回这个对象本身才能链式调用对象的其他方法

字符串拼接

 // 对象属性字符串拼接
 let myLang = {
   No1: "HTML",
   No2: "CSS",
   No3: "JavaScript",
   myStudyingLang: function (num) {
     // console.log(this.No + num) 这样打印不出来 因为this.No是undefined;
     console.log(this["No" + num]); // 这样才能打印出来,字符串拼接属性名时只能这样写
   },
 };
 myLang.myStudyingLang(1);
 obj = {
   name: "123",
 };
 console.log(obj["name"]);
 // 这样也能访问对象的属性
 // 因为js引擎会在你 obj.name 时 隐式转化成 obj['name']

对象枚举(遍历)

 // 对象枚举
 // 实际上是对象
 // 枚举 -> 遍历
 // 遍历是在一组信息内 一个一个按顺序获取信息的过程 就叫遍历
 // 有枚举就有遍历
 let arr = [1, 2, 3, 4, 5];
 for (let i = 0; i < arr.length; i++) {
   console.log(arr[i]);
 }
 let car = {
   brand: "Benz", // key : value
   color: "red",
   displacement: "3.0",
   lang: "4",
   width: "2.5",
 };
 for (let key in car) {
   console.log(key); //打印键名
   // console.log(car.key); 这样打印不出来value
   // car.key -> car['key'] -> 找不到'key' 所以是undefined
   console.log(key + ":" + car[key]);
 }
 let arr1 = [1, 2, 3, 4, 5];
 for (let i in arr1) {
   console.log(arr[i]);
   // for in 可以遍历对象 和数组
 }

hasOwnProperty

 // hasOwnProperty
 // 拷贝的问题
 let obj = {
   name: "张三",
   age: 18,
 };
 //obj.hasOwnProperty(obj.name); 不是false 就是 true
 function Car() {
   this.brand = "Benz";
   this.color = "red";
   this.displacement = "3,0";
 }
 Car.prototype = {
   lang: 5,
   width: 2.5,
 };
 let car = new Car();
 for (let key in car) {
   console.log(key + ":" + car[key]);
   // 原型上只要是自己设置的属性都会被打印出来(上层所有原型)
 }
 for (let key in car) {
   if (car.hasOwnProperty(key)) {
     console.log(car[key]);
   }
   // 找自身的属性不找原型上的属性
 }

instanceof

 // instanceof 非常重要
 // 题是肯定要靠的
 // 判断这个对象是否是该构造函数实例出来的
 function Car() {}
 let car = new Car();
 console.log(car instanceof Car); // true
 function Person() {}
 let p = new Person();
 console.log(p instanceof Car); // false
 console.log(car instanceof Object); // true
 console.log([] instanceof Array); // true
 console.log([] instanceof Object); // true
 // A对象的原型里到底有没有B的原型 在原型链里面只要他们重合的 结果都是true

Object.prototypetoString方法实际开发中的用法

 let a = [] || {};
 console.log(a.constructor); // Array()
 console.log(a instanceof Array); // true
 let str = Object.prototype.toString.call(a);
 if (str === "[object Array]") {
   console.log("是数组");
 } else {
   console.log("不是数组");
 }
 // 实际开发经常用到,后端传来的数据做判断
 {
   let str = Object.prototype.toString,
     trueTip = "[object Array]";
   if (str.call(a) === trueTip) {
     console.log();
   }
 }
 console.log(str); //[object Array]

复习this练习题

  • 第一题
 // 函数内部的this指向谁
 function test(b) {
   this.d = 3; // window.d = 3
   let a = 1;
   function c() {}
 }
 test(123);
 /* AO = {
     arguments: [123]
     this: window,
     b: 123,
     a: undefined,
     c: function c(){}
 } */
 // 函数内部的this在函数没运行时指向的是window
 // 此时的this.d 相当于window.d
  • 第二题
 function Test() {
   //var this = {
   // __proto__: Test.prototype
   // }
   this.name = "123";
 }
 let test = new Test();
 /*  AO ={
     this: window -> {
         name: '123',
         __proto__: Test.prototype
     }
 }
 GO = {
     Test: function test(){...}
     test: {}
 } */
 ​

apply练习题

function Person() {
  this.name = "张三";
  this.age = 18;
}
function Programmer() {
  Person.apply(this);
  this.work = "Programming";
}
let p = new Programmer();
console.log(p);
// 全局this -> window
// 预编译函数 this -> window
// apply / call 改变this指向
// 构造函数的this指向实例化对象

callee/caller

//caller

function test() {
  console.log(arguments.callee.length);
}
test(); // 0
function test1(a, b, c) {
  console.log(arguments.callee.length); // 返回实参指向的函数长度
  console.log(test.length); // 函数形参长度
  console.log(arguments.length); // 实参长度;
}
test(1, 2, 3); // 3
//arguments.callee
// 返回的是正在被执行的函数对象 执行到这一句 arguments指向的函数是谁就返回
{
  function test2() {
    console.log(arguments.callee);
    function test3() {
      console.log(arguments.callee);
    }
    test3();
  }
  test2();
  // 打印出两个函数
}
/* function sum(n) {
  if (n <= 1) {
    return 1;
  }
  return n + sum(n - 1);
}
let res = sum(10);
console.log(res); // 55 */
let sum = (function (n) {
  if (n <= 1) {
    return 1;
  }
  return n + arguments.callee(n - 1);
  // callee 不是找函数名 而是找这个函数
})(10);
console.log(sum);
// caller
function test1() {
  test2();
}
test1();
function test2() {
  console.log(test2.caller);
  // 返回当前被调用函数的函数引用
  // 所以放回test1 因为 是test1调用的test2
  // 必须被调用了才打印得出来
}
  • 严格模式下 这两个属性不能用

面试题

// 阿里机答题
function foo() {
  bar.apply(null, argument); // 相当于没有指定this
}
function bar() {
  console.log(arguments);
}
// bar() = bar.call(arguments) -> bar(arguments)

foo(1, 2, 3, 4, 5); // [1,2,3,4,5]
//JS的typeof可能返回的值有哪些?
// 'undefined' 'object(Null)' 'boolean' 'number' 'string' 'function'
function b(x, y, a) {
  arguments[2] = 10;
  alert(a); // 弹10
  a = 10;
  alert(arguments[2]); // 还是弹10 形参和实参有映射关系 在函数内改两者都会改变
}
b(1, 2, 3);
alert(123);
let f =
  (function f() {
    return "1";
  },
  function g() {
    return 2;
  });
console.log(typeof f); // 'Function'
undefined == null; //true
undefined === null; // false
isNaN("100"); // false 隐式转换成了数字
parseInt("1a") == 1; // true
function isNaN2(num) {
  let res = Number(num); // 这里把结果转换为字符串 加一个空字符串符号
  if (res == NaN) {
    // NaN不等于任何数 所以有问题 这里要判断字符串的NaN才行
    return true;
  } else {
    return FontFaceSetLoadEvent;
  }
}
console.log(isNaN2("123"));
undefined == null; //true
undefined === null; // false
isNaN("100"); // false 隐式转换成了数字
parseInt("1a") == 1; // true
function isNaN2(num) {
  let res = Number(num); // 这里把结果转换为字符串 加一个空字符串符号
  if (res == NaN) {
    // NaN不等于任何数 所以有问题 这里要判断字符串的NaN才行
    return true;
  } else {
    return FontFaceSetLoadEvent;
  }
}
console.log(isNaN2("123"));
// 面试题
// {} == {}  : 不等于
// 为什么不等于 :引用值对比的是地址 这是两个不同的对象存的地址都不同
// 怎么让两个对象相等 let obj = {}; obj1 = obj 这样两个对象就相等了
let a = "1";
function test() {
  let a = "2";
  this.a = "3";
  console.log(a);
}
test(); // 2
new test(); // 2
console.log(a); // 3

\