函数分类

  1. 普通函数;
  2. (所有的类: 内置类、自己创建的类)

对象分类

  1. 普通对象;

  2. 数组;

  3. 正则;

  4. 日期;

  5. Math;

  6. 实例 (除了基本类型的字面量创建的值)

  7. prototype 的值也是对象类型;

原型

  1. 每一个类 (函数) 都具备 prototype 并且属性值是一个对象;

  2. 这个原型对象上天生具备一个属性 constructor 指向类本身;

  3. 每一个对象 普通对象prototype实例函数等) 都有一个 __proto__ 属性,这个属性指向当前实例所属类的原型 prototype,如果不确定是谁的实例,一定都是 Object 的实例;

原型链

  1. 它是一种基于 __proto__ 向上查找的机制;

  2. 当操作某个属性或者方法的时候,首先在自己的私有空间中查找属性或者方法,其次沿着原型链查找:

    1. 若在私有空间找到了,则结束查找,使用自己的私有的即可;
    2. 若在私有空间没有找到,则基于 __proto__ 找所属的 prototype ,如果找到就使用这个公有的;如果没有找到,则基于 __proto__ 继续向上查找,一直找到 Object.prototype ,如果没有,则操作的属性或者方法不存在;

基础方法

W3C 不推荐直接使用系统成员 __proto__

API 描述
Object.getPrototypeOf(对象) 获取对象的隐式原型 __proto__
Object.prototype.isPrototypeOf(对象) 判断当前对象 (this) 是否在指定对象的原型链上
instanceof 判断函数的原型是否在对象的原型链上
Object.create(对象) 创建一个新对象,其隐式原型 __proto__ 指向指定的对象
Object.prototype.hasOwnProperty(属性名) 判断一个对象自身是否拥有某个属性

面试题

实现 n.plus(10).minus(5)

~ function anonymous(proto) {
  const checkNum = function checkNum(num) {
    // 判断 num 是否是有效数字类型
    num = Number(num);
    // isNaN 是否是 非有效数字
    if (isNaN(num)) {
        num = 0;
    }
    return num;
  };

  proto.plus = function plus(num) {
    // this:要操作的那个数字实例(对象)
    // 返回 Number 类的实例,实现链式写法
    return this + checkNum(num);
  };

  proto.minus = function minus(num) {
    return this - checkNum(num);
  };
}(Number.prototype);

let n = 10;
let m = n.plus(10).minus(5);
console.log(m); //=>15(10+10-5)

画图计算下面的结果

function fun() {
  this.a = 0;
  this.b = function () {
    alert(this.a);
  }
}

fun.prototype = {
  b: function () {
    this.a = 20;
    alert(this.a);
  },
  c: function () {
    this.a = 30;
    alert(this.a);
  }
}

var my_fun = new fun();
my_fun.b();
my_fun.c();

写出下面代码执行输出的结果

function C1(name) {
  // name:undefined 没有给实例设置私有的属性 name
  if (name) {
      this.name = name;
  }
}

function C2(name) {
  this.name = name;
  // 给实例设置私有属性 name => this.name=undefined
}

function C3(name) {
  this.name = name || 'join';
  // 给实例设置私有属性 name =>this.name=undefined || 'join'
}

C1.prototype.name = 'Tom';
C2.prototype.name = 'Tom';
C3.prototype.name = 'Tom';
alert((new C1().name) + (new C2().name) + (new C3().name));
//=> (new C1().name) 找原型上的 'Tom'
//=> (new C2().name) 找私有属性 undefined
//=> (new C3().name) 找私有属性 'join'

写出下面代码执行输出的结果(阿里)

function Foo() {
  //没有 this.XXX() 就不是私有方法
  getName = function () {
    console.log(1);
  };
  return this;
}

Foo.getName = function () {
  console.log(2);
};
Foo.prototype.getName = function () {
  console.log(3);
};

var getName = function () {
  console.log(4);
};
function getName() {
  console.log(5);
}

Foo.getName();// 2
getName();// 4
Foo().getName();// 1
getName();// 1

// new无参列表 优先级为18
// new有参列表 优先级为19
// 成员访问 优先级为19
// 先Foo.getName(),在new
new Foo.getName();// 2

// 先new,在调用.getName()
// Foo中没有this.getName,所以根据原型链向上查找
new Foo().getName();// 3

// 先 new Foo(),再.getName(),再 new 实例.getName,new 原型上的getName
new new Foo().getName();// 3

下面代码输出结果是什么?为什么?

JavaScript
JavaScript
// 题目
let obj = {
  2: 3,
  3: 4,
  length: 2,
  push: Array.prototype.push
}
obj.push(1);
obj.push(2);
console.log(obj);
// 解析
// 扩展:模拟 array.push 的实现
Array.prototype.push = function push(num) {
  // this:arr
  this.length = this.length || 0;
  // 拿原有 length 作为新增项的索引
  this[this.length] = num;
  // length 的长度会自动跟着累加 1
  this.length++
};
let arr = [10, 20]; //=>{ 0: 10, 1: 20, length: 2 }
arr.push(30);

let obj = {
  2: 3,
  3: 4,
  length: 2,
  push: Array.prototype.push
};
obj.push(1); // obj[2]=1  obj.length=3
obj.push(2); // obj[3]=2  obj.length=4
console.log(obj); // {2: 1, 3: 2, length: 4 ...}

let obj = {
  1: 10,
  push: Array.prototype.push
};
// this.length 默认值为 0
obj.push(20); // obj[obj.length]=20   obj[0]=20
console.log(obj); // {0:20,1:10,length:1...}
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 函数分类
  2. 2. 对象分类
  3. 3. 原型
  4. 4. 原型链
  5. 5. 基础方法
  6. 6. 面试题
    1. 6.1. 实现 n.plus(10).minus(5)
    2. 6.2. 画图计算下面的结果
    3. 6.3. 写出下面代码执行输出的结果
    4. 6.4. 写出下面代码执行输出的结果(阿里)
    5. 6.5. 下面代码输出结果是什么?为什么?