JS高级第一天:数据类型、继承、闭包、原型,前端面试题2024笔试

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024c (备注前端)
img

正文

  • 旧时代:

  • es1.0。。。es3.1

  • 新时代:

  • es5

  • es6(es2015)

  • es7(es2016)、es8(es2017)

数据类型


  • 基本数据类型——值类型:(数字、字符串、布尔值、null、undefined)

  • undefined类型?

  • 复杂数据类型——引用类型:(对象)

  • 数组

  • 函数

  • 正则表达式

  • Date

对象的基本使用


创建一个对象

var student={

name:“李白” , //student有一个name属性,值为"李白"

grade:“初一” ,

//a、student有一个say属性,值为一个函数

//b、student有一个say方法

say:function(){

console.log(“你好”);

},

run:function(speed){

console.log(“正在以”+speed+“米/秒的速度奔跑”);

}

}

对象是键值对的集合:对象是由属性和方法构成的 (ps:也有说法为:对象里面皆属性,认为方法也是一个属性)

  • name是属性 grade是属性

  • say是方法 run是方法

对象属性操作

获取属性:
第一种方式:.语法
  • student.name 获取到name属性的值,为:“李白”

  • student.say 获取到一个函数

第二种方式:[]语法
  • student[“name”] 等价于student.name

  • student[“say”] 等价于student.say

号外:2种方式的差异:
  • .语法更方便,但是坑比较多(有局限性),比如:

  • .后面不能使用js中的关键字、保留字(class、this、function。。。)

  • .后面不能使用数字

var obj={};

obj.this=5; //语法错误

obj.0=10; //语法错误

  • []使用更广泛

  • o1[变量name]

  • [“class”]、[“this”]都可以随意使用 obj["this"]=10

  • [0]、[1]、[2]也可以使用

  • obj[3]=50 = obj["3"]=50

  • 思考:为什么obj[3]=obj[“3”]

  • 甚至还可以这样用:[“[object Array]”]

  • jquery里面就有这样的实现

  • 也可以这样用:[“{abc}”]

  • 给对象添加了{abc}属性

设置属性
  • student["gender"]="男" 等价于: student.gender="男"

  • 含义:如果student对象中没有gender属性,就添加一个gender属性,值为"男"

如果student对象中有gender属性,就修改gender属性的值为"男"

  • 案例1:student.isFemale=true

  • 案例2:student["children"]=[1,2,5]

  • 案例3:

student.toShanghai=function(){

console.log(“正在去往上海的路上”)

}

删除属性
  • delete student[“gender”]

  • delete student.gender

通过构造函数创建对象


构造函数创建对象的例子:

  • var xiaoming = new Object() --> var xiaoming = {};

  • var now = new Date()

  • var rooms = new Array(1,3,5) --> var rooms = [1,3,5]

  • var isMale=/123/; ==> var isMale=new RegExp("123")

  • isMale是通过RegExp构造函数创建出来的对象

  • isMale是RegExp构造函数的实例

  • 以上例子中,Object、Date、Array都是内置的构造函数

自定义一个构造函数来创建对象


  • 构造函数

function Person(name,age){

this.name=name;

this.age=age;

}

var p1=new Person(“赵云”,18)

  • 说明:p1就是根据【Person构造函数】创建出来的对象

构造函数的概念

  • 任何函数都可以当成构造函数

function CreateFunc(){ }

  • 只要把一个函数通过new的方式来进行调用,我们就把这一次函数的调用方式称之为:构造函数的调用

  • new CreateFunc(); 此时CreateFunc就是一个构造函数

  • CreateFunc(); 此时的CreateFunc并不是构造函数

关于new Object()

  • new Object()等同于对象字面量{}

构造函数的执行过程

var p1=new Person();

  • 1、创建一个对象 (我们把这个对象称之为Person构造函数的实例)- _p1

  • 2、创建一个内部对象,this,将this指向该实例(_p1)

  • 3、执行函数内部的代码,其中,操作this的部分就是操作了该实例(_p1)

  • 4、返回值:

  • a、如果函数没有返回值(没有return语句),那么就会返回构造函数的实例(p1)

  • b、如果函数返回了一个基本数据类型的值,那么本次构造函数的返回值是该实例(_p1)

function fn(){

}

var f1=new fn(); //f1就是fn的实例

function fn2(){

return “abc”;

}

var f2=new fn2(); //f2是fn2构造函数的实例

  • c、如果函数返回了一个复杂数据类型的值,那么本次函数的返回值就是该值

function fn3(){

return [1,3,5];

//数组是一个对象类型的值,

//所以数组是一个复杂数据类型的值

//–>本次构造函数的真正返回值就是该数组

//–>不再是fn3构造函数的实例

}

var f3=new fn3(); //f3还是fn3的实例吗?错

//f3值为[1,3,5]

继承


JS中继承的概念:

  • 通过【某种方式】让一个对象可以访问到另一个对象中的属性和方法,我们把这种方式称之为继承 并不是所谓的xxx extends yyy

为什么要使用继承?

  • 有些对象会有方法(动作、行为),而这些方法都是函数,如果把这些方法和函数都放在构造函数中声明就会导致内存的浪费

function Person(){

this.say=function(){

console.log(“你好”)

}

}

var p1=new Person();

var p2=new Person();

console.log(p1.say === p2.say); //false

继承的第一种方式:原型链继承1

Person.prototype.say=function(){

console.log(“你好”)

}

  • 缺点:添加1、2个方法无所谓,但是如果方法很多会导致过多的代码冗余

继承的第二种方式:原型链继承2

Person.prototype = {

//切记不能忘记

constructor:Person,

say:function(){

console.log(“你好”);

},

run:function(){

console.log(“正在进行百米冲刺”);

}

}

  • 注意点:

  • a、一般情况下,应该先改变原型对象,再创建对象

  • b、一般情况下,对于新原型,会添加一个constructor属性,从而不破坏原有的原型对象的结构

继承的第三种方式:拷贝继承(混入继承:mixin)

  • 场景:有时候想使用某个对象中的属性,但是又不能直接修改它,于是就可以创建一个该对象的拷贝

  • 实际运用:

  • jquery:$.extend:编写jquery插件的必经之路

  • 基于jquery封装一个表格控件

var o1={ age:2 };

var o2 = o1;

o2.age=18;

//1、修改了o2对象的age属性

//2、由于o2对象跟o1对象是同一个对象

//3、所以此时o1对象的age属性也被修改了

var o3={gender:“男”,grade:“初三”,group:“第五组”,name:“张三”};

var o4={gender:“男”,grade:“初三”,group:“第五组”,name:“李四”};

//上述代码中,如果使用拷贝继承对代码进行优化会非常和谐

//实现拷贝继承:

//1、已经拥有了o3对象

//2、创建一个o3对象的拷贝(克隆):for…in循环

//3、修改克隆对象,把该对象的name属性改为"李四"

  • 实现1:

var source={name:“李白”,age:15}

var target={};

target.name=source.name

target.age=source.age;

  • 浅拷贝和深拷贝

  • 浅拷贝只是拷贝一层属性,没有内部对象

  • 深拷贝其实是利用了递归的原理,将对象的若干层属性拷贝出来

var students=[

{name:“”,age:“”},

{name:“”,age:“”}

]

  • 上面的方式很明显无法重用,实际代码编写过程中,很多时候都会使用拷贝继承的方式,所以为了重用,可以编写一个函数把他们封装起来:

function extend(target,source){

for(key in source){

target[key]=source[key];

}

return target;

}

extend(target,source)

  • 由于拷贝继承在实际开发中使用场景非常多,所以很多库都对此有了实现

  • jquery:$.extend

  • es6中有了 <对象扩展运算符> 仿佛就是专门为了拷贝继承而生:

  • 优点:简单的令人发指

var source={name:“李白”,age:15}

//让target是一个新对象,同时拥有了name、age属性

var target={ …source }

var target2={ …source,age:18 }

继承的第四种方式:原型式继承:(道格拉斯在蝴蝶书中提出来的)

  • 场景:

  • a、创建一个纯洁的对象:对象什么属性都没有

var parent={ age:18,gender:“男”};

var student=Object.create(parent);

//student.proto===parent

  • 使用方式:

  • 空对象:Object.create(null)

var o1={ say:function(){} }

var o2=Object.create(o1);

继承的第五种方式:借用构造函数实现继承

  • 场景:适用于2种构造函数之间逻辑有相似的情况

  • 原理:函数的call、apply调用方式

function Animal(name,age,gender){

this.name=name;

this.age=age;

this.gender=gender;

}

function Person(name,age,gender,say){

this.name=name;

this.age=age;

this.gender=gender;

this.say=function(){

}

}

  • 局限性:Animal(父类构造函数)的代码必须完全适用于Person(子类构造函数)

  • 以上代码用借用构造函数实现

function Animal(name,age){

this.name=name;

this.age=age;

}

function Person(name,age,address){

Animal.call(this,name);

//this.name=name;

//this.age=age;

this.address=address;

}

  • 寄生继承、寄生组合继承

原型链(家族族谱)


  • 概念:JS里面的对象可能会有父对象,父对象还会有父对象,。。。。。祖先

  • 根本:继承

  • 属性:对象中几乎都会有一个__proto__属性,指向他的父对象

-意义:可以实现让该对象访问到父对象中相关属性

  • 根对象:Object.prototype

  • var arr=[1,3,5]

  • arr.proto:Array.prototype

  • arr.proto.__proto__找到了根对象

function Animal(){}

var cat=new Animal();

//cat.proto:Animal.prototype

//cat.proto.proto:根对象

  • 错误的理解:万物继承自Object?

闭包


变量作用域

  • 变量作用域的概念:就是一个变量可以使用的范围

  • JS中首先有一个最外层的作用域:称之为全局作用域

  • JS中还可以通过函数创建出一个独立的作用域,其中函数可以嵌套,所以作用域也可以嵌套

var age=18; //age是在全局作用域中声明的变量:全局变量

function f1(){

console.log(name); //可以访问到name变量

var name=“周董” //name是f1函数内部声明的变量,所以name变量的作用域就是在f1函数内部

自学几个月前端,为什么感觉什么都没学到??


这种现象在很多的初学者和自学前端的同学中是比较的常见的。

因为自学走的弯路是比较的多的,会踩很多的坑,学习的过程中是比较的迷茫的。

最重要的是,在学习的过程中,不知道每个部分该学哪些知识点,学到什么程度才算好,学了能做什么。

很多自学的朋友往往都是自己去找资料学习的,资料上有的或许就学到了,资料上没有的或许就没有学到。

这就会给人一个错误的信息就是,我把资料上的学完了,估计也-就差不多的了。

但是真的是这样的吗?非也,因为很多人找的资料就是很基础的。学完了也就是掌握一点基础的东西。分享给你一份前端分析路线,你可以参考。

还有很多的同学在学习的过程中一味的追求学的速度,很快速的刷视频,写了后面忘了前面,最后什么都没有学到,什么都知道,但是什么都不懂,要具体说,也说不出个所以然。

所以学习编程一定要注重实践操作,练习敲代码的时间一定要多余看视频的时间。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
变量

var name=“周董” //name是f1函数内部声明的变量,所以name变量的作用域就是在f1函数内部

自学几个月前端,为什么感觉什么都没学到??


这种现象在很多的初学者和自学前端的同学中是比较的常见的。

因为自学走的弯路是比较的多的,会踩很多的坑,学习的过程中是比较的迷茫的。

最重要的是,在学习的过程中,不知道每个部分该学哪些知识点,学到什么程度才算好,学了能做什么。

很多自学的朋友往往都是自己去找资料学习的,资料上有的或许就学到了,资料上没有的或许就没有学到。

这就会给人一个错误的信息就是,我把资料上的学完了,估计也-就差不多的了。

但是真的是这样的吗?非也,因为很多人找的资料就是很基础的。学完了也就是掌握一点基础的东西。分享给你一份前端分析路线,你可以参考。

还有很多的同学在学习的过程中一味的追求学的速度,很快速的刷视频,写了后面忘了前面,最后什么都没有学到,什么都知道,但是什么都不懂,要具体说,也说不出个所以然。

所以学习编程一定要注重实践操作,练习敲代码的时间一定要多余看视频的时间。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-a221RUE2-1713321175564)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 25
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值