手撕三道js手写题

1,167 阅读3分钟

前言

万丈高楼平地起,一砖一瓦届地基。我觉得要来一波死磕 36 个 JS 手写题

三道js手写题

数据类型的判断

基础知识:

  1. js的数据类型分为基础类型和引用类型。 
     基础类型:   NumberNullUndefindStringBigInt, Boolean, Symbol。        
     引用类型:   Date, RegExp, Array, Function, Math
  2. 2. js中自带的判断数据类型
      typeof:
          typeof 可以识别基础数据类型 + function (但Null除外)
          (typeof null)  返回为 "object"
          虽然 typeof null 会输出 object,但这只是 JS 存在的一个悠久 Bug,
          不代表 null 就是引用数据类型,并且 null 本身也不是对象。
      instanceof:
          我们 new 一个对象,那么这个新对象就是它原型链继承上面的对象了,
          通过 instanceof 我们能判断这个对象是否是之前那个构造函数生成的对象,
          这样就基本可以判断出这个新对象的数据类型。
      Object.prototype.toString:
          toString() 是 Object 的原型方法,调用该方法,
          可以统一返回格式为 “[object Xxx]” 的字符串,
          其中 Xxx 就是对象的类型。对于 Object 对象,
          直接调用 toString() 就能返回 [object Object];
          而对于其他对象,则需要通过 call 来调用,才能返回正确的类型信息。
    

手写判断数据类型(返回 boolean 或 function)

function myTypeof(obj) {
    let datatype = Object.prototype.toString.call(obj)
    // 或者
    // datatype = datatype.slice(8, -1).toLowerCase();
    // 这句话的意思是让我们用Object原型上的toString方法
    // 作用在传入的obj的上下文中(通过call将this指向obj)
    datatype = datatype.split(' ')[1]
    // 用split切成数组, 并取数组的第两项
    datatype = datatype.splice(0, datatype.length-1).toLowerCase()
    return datatype;
}

js中的继承方法

第一种原型链继承

function Parent1() {
    this.name = 'parent1';
    this.play = [1, 2, 3]
  }
  function Child1() {
    this.type = 'child2';
  }
  Child1.prototype = new Parent1();

第二种构造函数继承

function Animal(name) {
    this.name = name;
    this.getName = function() {
        return this.name;
    }
}
function Dog(name) {
    Animal.call(this, name);
}
let a = new Dog('人类');
console.log(a.getName());

但是由于方法必须定义在构造函数中,所以会导致每次创建子类实例都会创建一遍方法。

第三种组合式继承

function Animal(name) {
    this.name = name;
    this.colors = ["白色", "黑色"];
}
Animal.prototype.getName = function() {
    return this.name;
}
function Dog(name, age) {
    Animal.call(this, name);
    this.age = age;
}
// Dog.prototype = new Animal()   
// 副作用 会把Dog.prototype.constructor Cat 变成Animal
// Dog.prototype.constructor = Dog;
// 或者直接
Dog.prototype.__proto__ == Animal.prototype;
console.log(Dog.prototype.constructor,'oooooooo');
let dog1 = new Dog('奶昔', 2)
dog1.colors.push('粉色')

let dog2 = new Dog('阿黄', 1);
dog2.colors.push('银白色');
console.log(dog2)

第四种寄生式继承

function clone (parent, child) {   
   //  寄生式继承使用了Object.create()
    // 这个方法接收两个参数:一是用作新对象原型的对象
    // 二是为新对象定义额外属性的对象(可选参数)
    // 这里改用 Object.create 就可以减少组合继承中多进行一次构造的过程
    child.prototype = Object.create(parent.prototype);
    //  child.prototype.__proto__   ->    parent.prototype
    child.prototype.constructor = child;
  }
function Parent6() {
  this.name = 'parent6';
  this.play = [1, 2, 3];
}
  Parent6.prototype.getName = function () {
  return this.name;
}
function Child6() {
  Parent6.call(this);
  this.friends = 'child5';
}
clone(Parent6, Child6);
Child6.prototype.getFriends = function () {
  return this.friends;
}
let person6 = new Child6();

console.log(person6);

console.log(person6.getName());

  console.log(person6.getFriends());

第五种extends继承


class Animal {
    constructor(name) {
        this.name = name
    } 
    getName() {
        return this.name
    }
}
class Dog extends Animal {
    constructor(name, age) {
        super(name)          
        // super指向的是当前对象的原型对象, 即为Animal
        this.age = age
    }
}

数组去重

第一种借用filter

function unique(arr) {
    //  filter() 方法创建一个新的数组,
    //  新数组中的元素是通过检查指定数组中符合条件的所有元素
    var res = arr.filter(function(item, index, array) {
        // console.log(array, 'array');
        return array.indexOf(item) === index
    })
    // item 	        必须。当前元素的值
    // index 	        可选。当前元素的索引值
    // array 	        可选。当前元素属于的数组对象
    return res
} 

第二种借用reduce

function unique1(arr) {
    let un = arr.reduce((pre,cur) =>{
        if(!pre.includes(cur)) {
            pre.push(cur)
        }
        return pre
    },[])
    return un
}

第三种Set结构

function unique2(arr) {
    return [...new Set(arr)]
    // Set也是一个构造函数,其数据结构类似于数组,
    // 但其不同之处在于永远没有重复的值 。
    // add(value):添加某个值,返回Set结构本身。 
    // delete(value):删除某个值,返回一个布尔值,表示删除是否成功。 
    // has(value):返回一个布尔值,表示该值是否为Set的成员。 
    // clear():清除所有成员,没有返回值。
}

第四种Map结构

function unique3(arr) {
    let map = new Map();
    console.log(map)
    //let arr1 = new Array();      // 数组用于返回结果
    let arr1 = []
    for (let i = 0, len = arr.length; i < len; i++) {
        if (map.has(arr[i])) {      // 判断是否存在该key值
            map.set(arr[i], true);
        }
        else {
            map.set(arr[i], false);
            arr1.push(arr[i]);
        }
    console.log(map)
    }
    return arr1;
}

后话

对象这种js手写题可以先看题干,再着手进行写出相关代码。