美文网首页
javascript知识点总结

javascript知识点总结

作者: 池鱼_故渊 | 来源:发表于2019-02-19 20:18 被阅读0次

1.原型 构造函数 实例

  • 原型(prototype):每当定义一个对象(函数也是对象)的时候,对象都会包含一些预定义的属性,其中每个函数对象都包含一个prototype属性,这个属性指向函数的原型对象
  • 构造函数:可以通过new 来新建一个对象的函数
  • 实例:通过构造函数和new创建出来的对象就是实例,实例通过_proto_指向原型,通过constructor指向构造函数
  • 每个对象都有_proto_属性,但是只有函数对象才有prototype属性

例子:
var obj={}等同于 var obj=new Object();
obj是构造函数(Object)的一个实例
obj.prototype就是一个原型对象(obj.prototype==原型对象)
obj._proto_ == Object.prototype
obj.constructor == Object
Object.prototype.constructor == Object

image.png

var person1 = new Person()
1.person1._proto_是什么?
因为person1._proto_ === person1的构造函数.prototype
因为person1的构造函数 === Person
所以 person1._proto_ === Person.prototype
2.Person._proto_是什么
因为Person._proto_ === Person的构造函数.prototype
因为Person的构造函数 === Function
所以Person._proto_ ===Function.prototype
3.Person.prototype._proto_是什么?
因为Person.prototype是一个普通的对象,一个普通对象的构造函数 ===Object
所以 Person.prototype._proto_ ===Object.prototype
4.Object.prototype._proto_是什么
Object.prototype对象也有_proto_属性,但是比较特殊,为null,处于原型链的顶端,所以Object.prototype._proto_ ===null

2.原型链

原型链是由原型对象组成,每个对象都有_proto_属性,指向了创建该对象的构造函数和原型,_proto_将原型对象链接起来组成了原型链,是用来实现继承和共享属性的有限对象链。

  • 属性查找机制:当查找对象属性时,如果实例对象自身不存在该属性,则沿着原型链向上一级查找,找到则输出,如果没找到,则沿着原型链继续向上查找,直到最顶层原型对象Object.prototype,如果还没有则输出undefined
  • 属性修改机制:只会修改实例对象本身的属性,如果不存在,则进行添加该属性,如果需要修改原型的属性时,则可以用: b.prototype.x = 2;但是这样会造成所有继承于该对象的实例的属性发生改变。

3.函数柯里化

在一个函数中,首先添加几个固定的参数,在返回一个新的函数,称为函数的柯里化,可以多次重复调用。
ES5实现高阶函数也叫函数的柯里化

function add(x){
    return function(y){
         return x+y
     }
}
var add2= add(2);
add2(3);          // => 5
add(10)(11);        // => 21

ES6箭头函数实现函数柯里化

const add= x=> y=> x+y;

4.闭包

function init() {
    var name = "Mozilla"; // name 是一个被 init 创建的局部变量
    function displayName() { // displayName() 是内部函数,一个闭包
        alert(name); // 使用了父函数中声明的变量
    }
    displayName();
}
init();

5.对象的深浅拷贝

对象的拷贝在js中比较常见

  • 浅拷贝:仅仅复制对象的引用,而不是对象本身,一旦修改拷贝对象,原对象也会被修改
  • 深拷贝:把复制的对象所有引用的对象全部拷贝包括地址,修改拷贝的对象,原对象不会改变。
1.浅拷贝

浅拷贝的方法比较简单,只是简单复制引用,,如果我们要复制对象的属性不引用类型就可以使用浅拷贝,
1.简单的赋值也属于浅拷贝

var obj = { age: '12',name:'jack' };
var newObj = obj;
//此时将obj中的age属性值改变,会发现newObj中的age属性值跟着改变
obj.age = '13';  //obj: { age: '13' }  newObj: { age: '13',name:''jack}

2.遍历复制,返回新对象

function shallowCopy(obj) {
    var copy = {};
    // 只复制可遍历的属性
    for (key in obj) {
        // 只复制本身拥有的属性
        if (obj.hasOwnProperty(key)) {
            copy[key] = obj[key];
        }
    }
    return copy;
}

obj.hasOwnProperty() MDN解释
这个方法可以用来检测一个对象是否含有特定的自身属性
语法:obj.hasOwnProperty(prop)
参数:要检测的属性 字符串 名称或者 Symbol
返回值: 用来判断某个对象是否含有指定的属性的 Boolean

3.js内部的浅拷贝
var newObj = Object.assign({}, originObj);其中第一个参数是我们最终复制的目标对象,后面的所有参数是我们的即将复制的源对象,支持对象或数组。
4.数组的浅拷贝
[].slice();
5.展开运算符
{...a}

2深拷贝

常用的有JSON.parse(),递归深拷贝,还有es5的object.create();
1.JSON.parse()
这种方法不支持json /正则/Data/undefined等
var a = {...}
var b = JSON.parse( JSON.stringify(a) )
2.递归深拷贝

function copy(obj1, obj2) {
    var obj = obj2 || {};
    for (var i in obj1) {
        var prop = obj1[i];
 
        // 避免相互引用对象导致死循环,如obj1.a = obj1的情况
        if(prop === obj) {
            continue;
        }
 
        if (typeof prop === 'object') {
            obj[i] = (prop.constructor === Array) ? [] : {};
            arguments.callee(prop, obj[i]);
        } else {
            obj[i] = prop;
        }
    }
    return obj;
}

3.object.create()

function deepClone(obj1, obj2) {
    var obj = obj2|| {};
    for (var i in obj1) {
        var prop = obj1[i];
 
        // 避免相互引用对象导致死循环,如obj1.a = obj1的情况
        if(prop === obj) {
            continue;
        }
 
        if (typeof prop === 'object') {
            obj[i] = (prop.constructor === Array) ? prop : Object.create(prop);
        } else {
            obj[i] = prop;
        }
    }
    return obj;
}

6.代码的复用

当你发现代码多次重复的时候,应该考虑代码的复用。

  • 函数封装
  • 继承
  • 复制extend

7.模块化

模块化开发是现在前端开发的重要部分,模块化提高了项目的可维护性和可拓展性、可协作性,在浏览器中ES6支持模块化,在Node中使用commonjs的模块支持

  • es6 :import /export
  • commonjs:require /module.exports /exports
  • amd: require /defined
    1.require支持动态导入,import不支持
    2.require是同步导入,import是异步导入
    3.require是值拷贝,导出值不会影响导入值,import指向内存地址,导入值会随导出值变化

8.this

1.全局环境/普通函数
在全局函数中,this永远指向window,普通函数的调用,不是构造函数没有使用new,其中this也是指向window

var a = 1;
function  fen(){
    console.log(this);//window
    console.log(this.a)//1
}
fen();

2.构造函数的this指向
构造函数就是指函数new出来的一个对象,

function Fen(){
     this.a= 1;
     console.log(this)//Fen{a:1}
}
var foo= new Fen();
console.log(foo.a)//10

如果函数作为构造函数使用,其中this就代表他new出来的对象,如果直接调用Fen()函数,而不是new Fen(),那么Fen()就是普通函数,this还是指向全局window
3.对象方法
如果函数作为对象的方法时,那么this指向该对象

var obj = {
    a:1,
    foo:function(){
         console.log(this)//Object
         console.log(this.a)//1
   }
}
obj.foo();

如果在对象方法中定义函数,

var obj = {
    a:1,
    foo:function(){
       function a(){
          console.log(this)//window
          console.log(this.a)//undefined
    }  
   a();
   }
}
obj.foo();

函数a虽然在obj.foo内部定义,但是依然是一个普通函数,this指向window,如果想调用变量a.可以把this.保存起来

var obj = {
    a:1,
    foo:function(){
      var that = this
       function a(){
          console.log(that)//{a:1}
          console.log(that.a)//1
    }  
   a();
   }
}
obj.foo();

如果foo函数不作为对象方法被调用

var obj = {
    a:1,
    foo:function(){
         console.log(this)//window
         console.log(this.a)//undefined
   }
}
var fn=obj.foo();
fn();

obj.foo被赋值给一个全局变量,并没有作为obj的一个属性被调用,那么此时this还是指向全局window
4.构造函数prototype属性

function Foo(){
   this.x=10
}
Foo.prototype.getX = function(){
    console.log(this)//Foo{x:10,getX:function}
    console.log(this.x)//10
}
var foo = new Foo();
foo.getX();

在Foo.prototype.getX函数中,this指向的foo对象,

5.call/apply/bind
当一个函数被call/apply/bind调用时,this的值就取传入的对象的值
6箭头函数的this
箭头函数本身没有this,箭头函数的内部的this是此法作用域,由上下文确定的

9.函数节流/函数防抖

  • 函数防抖:当调用一个动作几秒后才会执行动作,若在这几秒内又调用动作则重新计算时间执行函数(只有最后一次事件被触发)
  • 函数节流:预先设置一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个周期(一定时间内只触发一次)
    都是为了限制函数得执行次数,提高性能

1.防抖

//简单的理解就是在执行函数之前检查定时器是否已经存在
//如果存在说明之前已经触发了定时器,需要清除之前的定时器
//再重新生成一次定时器,重新执行
function debounce(fn,wait){
      let timer = null;
     let that = this;
      return function(){
           if(timer){
            clearTimeout(timer)
         }else{
          timer=setTimeout(()=>{
                fn.call(that,arguments)
//arguments 是类数组,指传入函数的参数
             },wait)
         }
     }
}
function fn(){
     console.log(1)
}
debounce(fn,1000);

/**
 * @desc 函数防抖
 * @param func 函数
 * @param wait 延迟执行毫秒数
 * @param immediate true 表立即执行,false 表非立即执行  第一次是否立刻触发
 */
function debounce(func,wait,immediate) {
    var timeout;

    return function () {
        var context = this;
        var args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            var callNow = !timeout;
//记录timeout是否为空,第一次为空所以为true,下面的判断会立即执行,等待防抖的时间timeout会被再次重置为空,如果在这个时间范围内,callNow会为false,所以不会执行下面的判断

            timeout = setTimeout(function(){
                timeout = null;
            }, wait)
            if (callNow) func.apply(context, args)
        }
        else {
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
    }
}

2.节流

// 简单的说就是再一个时间范围执行一次,不论这个范围内触发多少次,只执行一次
function throttle (fn,delay){
    var timer = null;
    var startTime = Date.now();
    return function(){
       var endTime = Date.now();
       var remaining = delay - (endTime - startTime);
       var context = this;
       var args = arguments;
       clearTimeout(timer);
      if(remaining<=0){
          fn.apply(context,args);
          startTime = Date.now();
       }else{
      timer = setTimeout(fn,remaining)
     }
    }
}
function  fn(){
    console.log(1)
}
throttle(fn,1000)

10.如何使用正则实现trim()?

function trim(string){
   return string.replace(/^\s + | \s + $/g," ")
}

11.手写AJAX

var xhr = new XMLHttpRequest();
xhr.open('GET',"/XXXX");
xhr.onreadystatechange = function(){
    if(xhr.readyState === 4){
       console.log('请求完成')
       if(xhr.response.status>=200 && xhr.response.status<=300){
                console.log(' 请求成功')
                console.log(xhr.responseText)
            }else{
             
           }
     }
}

12.数组去重

function fn (arr){
    var temp =[];
     for(var i =0;i<arr.length;i++){
            if(temp.indexOf(arr[i] )== -1){
                 temp.push(arr[i])
             }
         }
    return temp
}
fn(arrr)

es6去重

Array.from(new Set(arrr))

相关文章

  • 2019-04-24

    JavaScript简单知识点总结

  • 2021前端面试

    174道JavaScript 面试知识点总结(下) [Vue中文社区](javascript:void(0);) ...

  • js日期知识点总结

    javaScript 知识点总结: 创建日期的对象:var date = new Date(); date方法的含...

  • 短小精悍的javascript基础知识点

    注:本文所有知识点总结或摘抄自廖雪峰javascript教程,点击查看更详细的讲解。 1.javascript简介...

  • javascript你需要懂点

    下面小编就为大家带来一篇javaScript知识点总结(必看篇)。小编觉得挺不错的 1、javaScript的概念...

  • JavaScript知识点总结

    1.JAVA Script组成部分ECMAScript:它是整个javascript的核心,包含基本语法、变量、关...

  • JavaScript知识点总结

    1. JavaScript是作用于网络和HTML的一个编程语言。 2. JavaScript代码必须放在标签之间,...

  • JavaScript知识点总结

    JS概述 javscript : 1、ECMAScript js语法:标识符,关键字、变量、表达式、运算符、分支...

  • javascript知识点总结

    1.原型 构造函数 实例 原型(prototype):每当定义一个对象(函数也是对象)的时候,对象都会包含一些...

  • javascript知识点总结

    JavaScript入门js是什么?js即javascript,它是一种轻量级的脚本语言。运行在浏览器客户端.js...

网友评论

      本文标题:javascript知识点总结

      本文链接:https://www.haomeiwen.com/subject/qiooeqtx.html