能实现一个new吗
要实现new操作符,就要知道new + 构造函数都做了什么?
- 创建一个空的对象
- 将空对象的__proto__属性指向构造函数的原型
- 将this指向这个对象
- 返回这个对象
function newFun(context) {
// 创建一个空的对象
var obj = {}
// 将空对象的__proto__属性指向构造函数的原型
obj.__proto__ = context.prototype;
// 将this指向这个对象 将传入的实参分割出来指向obj上
context.apply(obj, [].slice.call(arguments, 1))
return obj;
}
function Person(name, age) {
this.name = name;
this.age = age
}
var t = newFun(Person, '小张', 20)
数组扁平化
通过不断递归+跳出条件
function newFlat(arr) {
let res = new Array()
arr.forEach((item) => {
if (Array.isArray(item)) {
res.push(...newFlat(item))
} else {
res.push(item)
}
})
return res
}
用过instanceof吗,什么用法,如何手写?
首先要知道是怎么用的?
instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上
实例 instanceof 构造函数存在返回true不存在false
例子
function Person(name, age, city) {
this.name = name;
this.age = age;
this.city = city
}
const a = new Person('小王', 20, '上海')
console.log(a instanceof Person) // true
知道了instanceof的用法之后手动实现instanceof
function instanceOf(instance, constructor) {
let prototype = constructor.prototype
while(true) {
if (instance == null) {
return false
}
if (instance.__proto__ == constructor.prototype) {
return true
}
instance = instance.__proto__
}
}
// 测试
function Person(name, age) {
this.name = name;
this.age = age;
}
let a = new Person('小明', 20);
console.log(instance_of(a, Person)) // true
防抖节流
防抖: 事件被调用后,在执行之前无论被调用多少次都会从头开始计时
节流: 不管事件被调用多少次,总是按照规定时间间隔执行
防抖
function debounce(fn, delay) {
let timer = null;
return (...args) => {
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
// 第二种
function debounce(fn, wait) {
var timeout = null;
return function() {
if(timeout !== null) clearTimeout(timeout);
timeout = setTimeout(fn, wait);
}
}
节流
通过一个控制阀+定时器
function throttle(fn, delay) {
let valid = true
return function() {
if(!vlaid) {
return false
}
valid = false
setTimeout(() => {
fn()
valid = true
}, delay)
}
}
call和apply和bind的区别
call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象
第二个参数是
call是按照顺序放进去
apply以数组的形式放进去
bind按照顺序放进去并且返回一个新的函数
call apply和bind每一个函数身上都会用这个方法,我们可以理解为是在Function的原型上面的方法
arguments
其实Javascript并没有重载函数的功能,但是Arguments对象能够模拟重载。Javascrip中每个函数都会有一个Arguments对象实例arguments,它引用着函数的实参,可以用数组下标的方式"[]"引用arguments的元素。arguments.length为函数实参个数,arguments.callee引用函数自身。
arguments他的特性和使用方法
特性:
1.arguments对象和Function是分不开的。
2.因为arguments这个对象不能显式创建。
3.arguments对象只有函数开始时才可用。
实现
Function.prototype.myCall = function(context) {
// context存在取context不存在取window
const cxt = context || window;
// 现在cxt上面添加一个函数指向this
cxt.func = this;
// 拿到传递的参数列表
const args = Array.from(arguments).slice(1)
const res = arguments.length > 1 ? cxt.func(...args) : cxt.func()
delete cxt.func;
return res;
}
Function.prototype.myApply = function(context) {
const cxt = context || window;
cxt.func = this;
const res = arguments[1] ? cxt.func(...arguments[1]) : cxt.func();
delete cxt.func;
return res;
}
Function.prototype.myBind = function(context) {
const cxt = JSON.parse(JSON.stringify(context) || window);
cxt.func = this;
const args = Array.from(arguments).slice(1)
return function() {
const allArgs = args.concat(Array.from(arguments))
return allArgs.length > 0 ? cxt.func(...allArgs) : cxt.func()
}
}
es5和es6继承
继承的区别:
在ES5中: 通过原型链实现继承,实质上是先创造子类的实例对象this,然后再将父类的方法添加到this上面,常见的继承方法是组合继承和寄生组合继承,
在ES6中,通过class进行继承,实质上是先将父类实例对象的属性和方法加到this上面,(所以必须先调用super),然后再用子类的构造函数修改this指向
function Human(name) {
this.name = name;
}
Human.prototype.run = function() {
console.log('走你')
}
function Man() {
this.sex = '男'
}
Man.prototype.habit = function() {
console.log('喜欢女人')
}
var object = new Man()
object //
当前这个Man有性别,但是还没有名字,还没有一些行为,如何让他有行为,让Man继承Human的属性和方法,进一步的写就是
function Human(name) {
this.name = name;
}
Human.prototype.run = function() {
console.log('走你')
}
function Man(name) {
this.sex = '男'
// 我们希望这里面把Human自己的属性和方法加到Man上面
// 并且让this指向Man的实例对象
// 所以我们就需要在这里调用Human并且把Man里面的this传给他
Human.call(this, name)
}
Man.prototype.habit = function() {
console.log('喜欢女人')
}
var object = new Man()
object //
es6继承
class Human{
constructor(name){
this.name = name
}
run(){
console.log('走你')
}
}
class Man extends Human{
constructor(name){
super(name)
this.sex='男'
}
habit(){
console.log('喜欢女人')
}
}
es6类的写法: 自身的属性写在constructor里面,方法写在constructor同级,相当于写在prototype上面
Man extends Human == Man.prototype.proto = Human.prototype