抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

  1. 面向对象编程思维
    • 提高代码的可复用率 => 更加合理的数据关系
  2. 隐式原型和显式原型
    • 对象的隐式原型和构造函数的显式原型的连接
  3. 原型链机制核心
    a. new: 执行前绑定this并指向空对象, 将对象的隐式原型指向函数的显式原型
    b. [[GET]]

Object和Function

关键点

  1. Object.prototype.__proto__ = null => 原型链的终点; 不是所有对象都是Object的实例
  2. Function.prototype.__proto__ = Object.prototype => new Object()
  3. Object.__proto__ = Function.prototype => new Function()
  4. Function.__proto__ = Function.prototype => 指向自己, 执行前通过代码注入

instanceof方法

instanceof

a instanceof Func

  1. 本质:递归
  2. 作用:判断 a 是不是 Func 的一个实例
    • s1.__proto__ = Student.prototype -> false
    • Student.prototype.__proto__ = Object.prototype -> true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Student(name, sex, age, major) {
this.name = name;
this.sex = sex;
this.age = age;
this.major = major;
}

var s1 = new Student('jack', 18, 'male', 'cs');
var s2 = new Student('lucy', 20, 'female', 'english');

// 自己封装instanceof
Object.myInstanceOf = function(obj, Func) {
if(obj === null) return false;
if(Object.getPrototypeOf(obj) === Fun.prototype) {
return true;
}else {
return myInstanceOf(Object.getPrototypeOf(obj, Func));
}
}
// Object.getPrototypeOf() -> 返回对象的隐式原型

数组和类数组

数组和类数组的区别

本质上是原型链上的区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var a = ['1', '2', '3'];
// 数组
a = {
'0': 1,
'1': 2,
'2': 3,
length: 3,
__proto__: Array.prototype
};
// 类数组
a = {
'0': 1,
'1': 2,
'2': 3,
length: 3,
__proto__: xxx
};

function demo() {
console.log(arguments);
}

demo(1, 2, 3);

隐式原型的修改

隐式原型的修改

  • Object.getPrototypeOf(obj) -> 返回参数对象的隐式原型
  • Object.setPrototypeOf(obj, obj) // 不推荐
  • Object.create() // 返回一个以obj为隐式原型的值的对象
    • 如何得到一个没有任何属性的对象
      var o = Object.create(null);

[[PUT]]&&[[GET]]

[[PUT]]

[[PUT]] -> LHS 左查询

  1. 判断对象中有没有属性
    • 如果有, 就找到并返回该地址
  2. 如果没找到
    • (1) 沿着原型链找
      • A. 找到这个属性
        • (a). 如果是基本类型 -> 覆盖 -> 在对象自身创建这个属性并返回
        • (b). 引用类型:
          • xxx. 对引用类型的引用 -> 覆盖
          • yyy. 对引用类型的访问 -> 修改
    • (2) 没有找到 -> 直到原型链终点 -> 给对象自身创建一个
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
45
46
47
48
49
50
var bar = new Object();

// 找到该属性并且是基本类型
// bar.prototype.b = 1;

// bar.b = 2;
// console.log(bar)
/** 返回结果: b为基本类型, 会在自身创建属性并返回, 原型链上不变
* bar {
* b: 2,
* [[prototype]]: Object {
* b: 1
* }
* }
*/

// 找到该属性并且是引用类型 -- 访问
Object.prototype.demo = {
m: 1,
}
// bar.demo.m = 2;
// console.log(Object.prototype);
/** 返回结果 对引用类型的访问会修改
* Object {
* demo: {
* m: 2,
* }
* }
*/

// 找到该属性 -- 对引用类型的引用
bar.demo = 2;
console.log(bar);
/** 返回结果 对引用类型的引用会覆盖
* bar {
* demo: 2,
* [[prototype]]: Object {
* demo: { m: 1 },
* }
* }
*/

bar.a = 1 // 会在对象自身创建

/** 返回
* bar {
* a: 1,
* [[prototype]]: Object
* }
*/

面试题

面试题 - 01

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function A() {}
A.prototype.n = 3;
A.prototype.add1 = function () {
this.n++;
// this.n = this.n + 1 RHS [[GET]]
// 左边this.n => LHS -> [[PUT]] => 基本类型(自身创建覆盖) => A { n: 4 }
}

var a = new A();
var b = new A();
var c = new A()
a.add1();
/** 分析 通过点(.)的方式调用函数会绑定this
* (1). a.add1 -> 属于RHS: 读操作,获取a.add1的返回值
* (2). RHS -> [[GET]] -> a.[[__proto__]] -> A.prototype.[[__proto__]]
*/
b.add1();
console.log(a.n, b.n, c.n); // 4, 4, 3

面试题 - 02

1
2
3
4
5
6
7
8
9
10
11
function A () {};
A.prototype.m = {
t: 1,
};
A.prototype.add2 = function() {
this.m = {}; // 写操作 => 对引用对象的引用 => 覆盖 => d { m: {}, prototype: Object { add2: f(), m: {t: 1}}}
// LHS -> [[PUT]]
}
var d = new A();
d.add2(); // RHS => [[GET]] -> d.[[__proto__]] -> A.prototype
console.log(d.m.t); // undefined

面试题 - 03

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Person(name, age) {
this.name = name;
this.age = age;
this.eat = function() {
console.log(age + "岁的" + name + "在吃饭.");
};
}

Person.run = function() {};
Person.prototype.walk = function () {};

let p1 = new Person('jsliang', 24);
let p2 = new Person('jsliang', 24);

// 对象的引用的值判断 -> 判断地址
console.log(p1.eat === p2.eat); // false => new的时候指向不同的地址
console.log(p1.run === p2.run); // true
console.log(p1.walk === p2.walk); // true

面试题 - 04

1
2
3
4
5
6
7
8
9
10
11
12
function foo() {
this.some = '222'; // 能访问到
let ccc = 'ccc';
foo.obkorou1= 'obkorou1';
foo.prototype.a = 'aaa'; // 能访问到
}
foo.koro = '扣肉';
foo.prototype.test = 'test' // 被修改
let foo1 = new foo();
foo.prototype.test = 'test2'; // 能访问到

// foo1 访问到哪些属性?

评论