对象属性遍历、this、caller_callee(十三)

2020/6/16 JS

# 一、链式调用

var sched = {
  wakeup: 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;
  }
}
// 每次函数调用后返回this
sched.wakeup().morning().noon().afternoon().evening().night();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 二、对象属性遍历

# 2.1 访问对象属性

obj[key]访问对象属性值,key(String)。

var myLang = {
  No1: 'HTML',
  No2: 'CSS',
  No3: 'JavaScript',
  myStudyingLang: function (num) {
    console.log(this['No' + num]);
  }
}

myLang.myStudyingLang(2); // 'CSS'
1
2
3
4
5
6
7
8
9
10

# 2.2 for...in

遍历一个对象的除Symbol以外的可枚举属性(包括原型上的可枚举属性)。

var arr = [1, 2, 3, 4, 5];

for (var i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}

for (var i in arr) {
  console.log(arr[i]);
}

var car = {
  brand: 'Benz',
  color: 'red',
  displacement: '3.0',
  lang: '5',
  width: '2.5'
}

for (var key in car) {
  // car.key -> car['key'] -> undefined
  // console.log(car.key); // undefined
  console.log(key + ':' + car[key]);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 2.3 hasOwnProperty()

返回一个布尔值,指示对象自身属性中是否具有指定的属性。

function Car() {
  this.brand = 'Benz';
  this.color = 'red';
  this.displacement = '3.0';
}

Car.prototype = {
  lang: 5,
  width: 2.5
}

Object.prototype.name = 'Object';

var car = new Car();

for (var key in car) {
  if(car.hasOwnProperty(key)) {
    console.log('自身属性' + key + ':' + car[key]);
  } else {
    console.log('原型链上的属性' + key + ':' + car[key]);
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 2.4 in

如果指定的属性在指定的对象或其原型链中,则in运算符返回true。

var car = {
  brand: 'Benz',
  color: 'red'
}

// car['displacement']
console.log('displacement' in car); // false
//-----------------------------------------------------------------------------------------------
function Car() {
  this.brand = 'Benz';
  this.color = 'red';
}

Car.prototype = {
  displacement: '3.0'
}

var car = new Car();

console.log('displacement' in car); // true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 2.5 instanceof

用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上。

function Car() {}
var car = new Car();

console.log(car instanceof Car);   // true
console.log(car instanceof Object);// true
console.log([] instanceof Array);  // true
console.log([] instanceof Object); // true
console.log({} instanceof Object); // true
1
2
3
4
5
6
7
8

# 2.6 判断数组的方法

var a = [];

console.log(a.constructor);
console.log(a instanceof Array);
var str = Object.prototype.toString.call(a);
if (str === '[object Array]') {
  console.log('是数组');
} else {
  console.log('不是数组');
}
console.log(str);
1
2
3
4
5
6
7
8
9
10
11

# 三、this

# 3.1 全局this -> window

# 3.2 构造函数的this指向实例化对象

/**
 * AO = {
 *  arguments: [123]
 *  this: window
 *  b: undefined -> 123
 *  a: undefined
 *  c: function c() {}
 * 
 * }
 * 
 */
function test(b) {
  this.d = 3; // window.d = 3 === d = 3
  var a = 1;
  function c() {}
}

test(123);

console.log(d); // 3
console.log(this.d); // 3
console.log(window.d); // 3
//----------------------------------------------------------------------------------------------
/**
 * AO = {
 *  this: window -> {
 *  name: '123,
 *  __proto__: Test.prototype
 * }
 * }
 * 
 * GO = {
 *  Test: function test() {...}
 *  test: {
 *  name: '123,
 *  __proto__: Test.prototype
 * }
 * }
 */
function Test() {
  this.name = '123';
}

var test = new Test();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

# 3.3 apply/call 改变this指向

function Person() {
  this.name = '张三';
  this.age = 18
}

function Programmer() {
  // 等价于
  // this.name = '张三';
  // this.age = 18;
  Person.apply(this);
  this.work = 'Programming'
}

var p = new Programmer();
console.log(p);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 四、caller、callee

# 4.1 arguments.callee

指向参数所属的当前执行的函数。

function test(a, b, c) {
  console.log(arguments.callee.length); // 3
  console.log(test.length); // 3
  console.log(arguments.length); // 2
}
test(1, 2)

function test1() {
  console.log(arguments.callee);
  function test2() {
    console.log(arguments.callee);
  }
  test2();
}
test1();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function sum(n) {
  if (n <= 1) {
    return 1;
  }
  return n + sum(n - 1);
}
//--------------------------------------------------------------------------------
var sum = (function (n) {
  if (n <= 1) {
    return 1;
  }
  return n + arguments.callee(n - 1)
})(100);

console.log(sum);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 4.2 caller

返回调用指定函数的函数。

test1();
function test1() {
  test2();
}

function test2() {
  console.log(test2.caller);
}
1
2
3
4
5
6
7
8

# 五、练习题

# 题目1

function foo() {
  bar.apply(null, arguments);
}

function bar() {
  console.log(arguments); // [1, 2, 3, 4, 5]
}

foo(1, 2, 3, 4, 5);
1
2
3
4
5
6
7
8
9

# 题目2

JS的typeof可能返回的值有哪些? object(null)/boolean/number/string/undefined/function/bigint(es2015)/symbol(es2020)

# 题目3

function b(x, y, a) {
  arguments[2] = 10;
  alert(a); // 10
}

b(1, 2, 3);
1
2
3
4
5
6

# 题目4

var f = (
  function f() {
    return '1';
  },
  function g() {
    return 2;
  }
)();

console.log(typeof(f)); // 'number'
1
2
3
4
5
6
7
8
9
10

# 题目5

console.log(undefined == null);  // true
console.log(undefined === null); // false
console.log(isNaN('100')); 		 // false
console.log(parseInt('1a'));     // 1
1
2
3
4

# 题目6

var a = '1';
function test() {
  var a = '2';
  this.a = '3';
  console.log(a);
}
test(); // '2'
new test(); // '2'
console.log(a); // '3'
1
2
3
4
5
6
7
8
9

# 题目7

var a = 5;
function test() {
  a = 0;
  console.log(a); // 0  0
  console.log(this.a); // 5 undefined
  var a;
  console.log(a); // 0 0
}
test();
new test();
1
2
3
4
5
6
7
8
9
10
Last Updated: 2022/7/21 10:52:53
Genshin Impact bgm
Genshin Impact