前端知识——js部分

js

Number对象哪个方法1把数字转换为字符串,使用本地数字格式顺序。

toLocaleString() 方法返回这个数字在特定语言环境下的表示字符串。

parseInt,parseFloat

parseInt () 忽略前面空格,解析数字,直到非数字停止;
识别各种进制的数,多进制转十进制
parseInt(11,8) //9
parseFloat()忽略字符串前面空格,从第一个字符开始解析直到遇见一个无效的浮点数字字符为止(第二个".")

[1,2,3].map(parseInt)
//[1, NaN, NaN]
[1,2,3].map(parseFloat)
//[1, 2, 3]

parseInt和parseFloat的区别

Math.round(),Math.ceil(),Math.floor()的区别

区别

domready和onload事件的区别:

  • 前者是在dom文档结构准备完毕之后就可以对DOM进行操作
  • 后者是当页面完全加载完毕之后(整个document文档包括图片、css外部资源文件、js文件)就会触发window上的load事件
  • Dom文档加载的步骤:
  1. 解析html结构
  2. 加载外部脚本和样式表文件
  3. 解析并执行脚本
  4. dom树构建完成
  5. 加载图片等外部文件
  6. 页面加载完毕

DOM ready是在第四步完成之后触发
图片 Load是在第五步完成之后触发
onLoad是在第六步完成之后触发

元素绑定事件与解绑

方法一:

        var btn=document.getElementById("event");
        btn.onclick=function(){
            alert("点我了!")
        }
        btn.onclick=null;

方法二:

        var btn=document.getElementById("event");
        function f1(){
            alert("点我了!")
        }
        btn.addEventListener("click",f1,false)//false冒泡,true捕获
        btn.removeEventListener("click",f1,false);

方法三:
浏览器已经不支持了。

  var btn=document.getElementById("event");
        function f1(){
            alert("点我了!")
        }
        btn.attachEvent('onclick',f1);
        btn.detachEvent("onclick",f1);

for in /of

for(let key in obj) 遍历的是key
for (let key of obj) 遍历的是内容,且不能遍历纯对象,可以是数组、字符串等。

深浅拷贝

原始类型浅拷贝:
方法一:

// 现在想把对象A的值复制给B,由于对象A的两个值都是原始类型,用浅复制即可

function copy(sub, sup) {
  for (var key in sup) {
    sub[key] = sup[key];
  }
}
copy(objB, objA);

方法二:
一层深,二层浅
IE不支持 Object.assign

object.assign(目标对象,需要复制的对象1,23)

方法三:
lodash

var obj2=_.clone(obj)

方法四:

var obj2={...obj}

方法五:
数组中concat和slice方法

var obj2=[]
console.log(obj2.concat(obj))

var obj=[1,2,{a:1}]
//slice最后一个不包括在内
var obj2=obj.slice(0,obj.length)
console.log(obj2)

深拷贝:
方法一:
只能处理json能理解的数据格式
JSON.parse(JSON.stringify(obj))

var obj=[1,2,{a:1}]
var obj2=JSON.parse(JSON.stringify(obj))
obj[2].a=2;
console.log(obj)// a=1
console.log(obj2)// a=2

方法二:
lodash _.cloneDeep()

var obj2=_.cloneDeep(obj)

方法三:
自己实现:

function deepCopy (obj) {
    var result;

    //引用类型分数组和对象分别递归
    if (Object.prototype.toString.call(obj) == '[object Array]') {
      result = []
      for (i = 0; i < obj.length; i++) {
        result[i] = deepCopy(obj[i])
      }
    } else if (Object.prototype.toString.call(obj) == '[object Object]') {
      result = {}
      for (var attr in obj) {
        result[attr] = deepCopy(obj[attr])
      }
    }
    //值类型直接返回
    else {
      return obj
    }
    return result
}

call,apply,bind:

作用:都是用来改变this指向的。
接受参数不同:call,bind传参用‘,’分隔,而apply是传入数组
如果call()和apply()的第一个参数是null或者undefined,那么this的指向就是全局变量,在浏览器里就是window对象。


var cat = {
  name:"喵喵",
  eatFish:function(param1,param2){
    console.log("吃鱼");
	console.log("this的指向=>");
	console.log(this);
	console.log(param1,param2);
  }
}
 
var dog = {
	name:"汪汪",
	eatBone:function(param1,param2){
		console.log("啃骨头");
		console.log("this的指向=>");
		console.log(this);
		console.log(param1,param2)
	}


//第一种,用call方法
cat.eatFish.call(dog,"旺财-13岁","call");

//第二种,用apply方法,参数不一样
cat.eatFish.apply(dog,["旺财-13岁","apply"]);

//把吃鱼的方法教给dog,在这里已经传参,返回的函数就不需要传参了。
var eatFishFun = cat.eatFish.bind(dog,"旺财-13岁","bind"); //返回的是方法
eatFishFun();

js垃圾回收

栈内存:栈内存调用栈上下文切换后就被回收,比较简单
堆内存的回收:V8堆内存分为新生代内存和老生代内存,新生代内存是临时分配的内存,存在时间段,老生代内存存在时间长。
新生代内存回收机制:FROM TO两部分,先扫描FROM,将非存活对象回收,将存活对象复制到To中,之后调换FROM/to 等待下一次回收
老生代内存回收机制
晋升:如果新生代变量经过多次回收仍然存在,则被放入老生代内存
标记清除:老生代内存会先遍历所有对象并打上标记,然后对正在使用或者被强引用的对象取消标记,回收被标记的对象。
整理内存碎片:把对象挪到内存的一段。
垃圾回收

写一个闭包

function books(){
    var book='书包里的书本'
    return function(){
    console.log(book);
    }
}
books();

本来外部是无法访问函数里面的变量的,通过闭包,外部就有权访问内部变量了。
解决setTimeOut的闭包问题:
用立即执行函数:

for(var i=0;i<5;i++){
(function(x){
   setTimeOut(function(){
   console.log(x++);
   },4000)
})(i);
}
//创建全局执行上下文 变量i
//创建立即函数执行上下文 变量x 进入任务队列
//再退出,再次创建立即函数执行上下文,重复
//任务队列里面有数值0 1 2 3 4
//输出0 1 2 3 4

写原型链

prototype是函数才有的属性,_proto_是每个对象都有的属性
大多数情况下,proto__可以理解为“构造器的原型”,即__proto===constructor.prototype,但是通过 Object.create()创建的对象有可能不是, Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象。
prototype就是原型
当一个对象调用的属性、方法自身不存在时,就会去自己_proto_关联的prototype去找,依次递增,直至找到最顶层。
原型链特点:
js对象是通过引用传递的,修改原型时,与之相关的对象也会继承这一改变。

arr=[]
//原型对象
arr.__proto__==Array.prototype
//Array的原型对象为Object
Array.prototype.__proto__==Object.prototype
//object的原型对象为null
Object.prototype.__proto__==null
//构造函数的proto
Array.__proto__==Function.prototype
//构造函数的proto=函数的prototype
Function.__proto__==Function.prototype

this理解

js 中的指向
普通函数

  • this在函数定义时确定不了,只有在函数执行时才能确定this到底指向谁,最终指向的是那个调用它的对象。
  • 看的是最后执行时是谁调用的。
  • 没有明确调用对象,返回window;
var a=11
function test1(){
  this.a=22;
  let b=function(){
    console.log(this.a);
  };
  b();
}
var x=new test1();
//输出11

es6 箭头函数的this:

  • this在定义时绑定。
  • 不能通过call、apply、bind来改变this值,但可以调用方法;
  • 没有arguments对象
  • 一般this指向全局对象
var a = 10
var obj = {
  a: 20,
  say: () => {
    console.log(this.a)
  }
}
obj.say() 
var anotherobj={a:30}
obj.say.apply(anotherobj)
正确答案: 10 10
  • 箭头函数没有this,会继承外部函数的this;
var a=11;
function test2(){
  this.a=22;
  let b=()=>{console.log(this.a)}
  b();
}
var x=new test2();
//输出22

在这里插入图片描述

  • 其他题目:
--------------------
name='ni'
var obj={
    name:'qunaer',
    Hi:function(){
        console.log(this.name)
    }
}
obj.Hi();
var obj2=obj.Hi();
obj2();

qunaer qunaer
//变量name不加var就变成了全局变量
---------------------

name='ni'
var obj={
    name:'qunaer',
    Hi:()=>{
        console.log(this.name)
    }
}
obj.Hi();
var obj2=obj.Hi();
obj2();

ni ni
--------------------

继承的方式及实现。

共六种:原型链、借用构造函数、组合式、原型式、寄生式、寄生组合式

function Person(name){
    this.name=name;
    this.like=["computer","swimming"] 
    this.age=10;//父类实例属性
}
Person.prototype.func=function(){
    return this.name;
}; //父类原型方法

1.原型链继承

function Student(){
}
Student.prototype=new Person();
var instance=new Student();

console.log(instance);//继承了属性
console.log(instance instanceof Student) //true
console.log(instance instanceof Person)  //true
instance.like.push("singing");
console.log(instance.__proto__) //所有实例共享,会受影响
console.log(instance.func())//继承了原型上的函数

原型链继承问题:
1.会共享父辈属性,在子辈中更改属性,其他都会受影响
2.创建子类型的实例时,不能向超类型的构造函数中传参;

2.构造函数继承

function Student(){
    Person.call(this,"Geoge");
}
var instance=new Student();
var instance2=new Student();
console.log(instance);
console.log(instance instanceof Student) //true
console.log(instance instanceof Person);   //false
instance.like.push("singing") 
console.log(instance.like); // [ 'computer', 'swimming', 'singing' ]
console.log(instance2.like);//[ 'computer', 'swimming' ]
console.log(instance.func) //undefined 不能继承父类原型上的属性和方法

特点:
1.解决了共享属性问题
2.可以向超类传递参数;
缺点:
1.方法都在构造函数中定义,无法复用
2.子类看不到超类,原型链上没有Person

3.组合式继承

function Student(name){   //解决不共享
    Person.call(this,name);
    this.hi="hi";
}
Student.prototype=new Person();   //解决在原型链上的问题;继承原型属性和方法。
Student.prototype.constructor=Student;  //一定要修改指向

var instance=new Student("jojo")
var instance2=new Student("haha")
console.log(instance instanceof Student)//true
console.log(instance instanceof Person);//true
console.log(instance)
instance.like.push("singing") 
console.log(instance.like); //[ 'computer', 'swimming', 'singing' ]
console.log(instance2.like);//[ 'computer', 'swimming' ]
console.log(instance.age) //10

解决上述问题后:不共享,可以继承原型属性。
缺点:会调用两次Person,在Student的原型上多创建非必要的属性。
4.寄生组合式继承
包括原型式继承和寄生式继承;
特点:解决组合继承两次调用父类构造函数问题;
优点:相比组合继承,只用调用一次父类方法,避免了父类在Student上创建的不必要,多余属性。

//原型式继承 等于把所需要继承的父类进行一次浅复制; 同样有原型链的问题;
function object(obj){
    function F(){};
    F.prototype=obj;
    return new F();
}
//寄生式继承 创建新对象,增强对象,返回对象 不能函数复用
function inheritPrototype(SubType,SuperType){
    var prototype=object(Person.prototype);
    prototype.constructor=Student;
    Student.prototype=prototype;
}

function Student(name){
    Person.call(this,name)
}
inheritPrototype(Student,Person);
var instance=new Student("lala");
console.log(instance);

es6去重,es5去重(手写)

forEach、Map

promise,async,await

generator与async,await区别

js运行机制,举例说明

数组中push一个数据,视图更新吗

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页