一些前端面试的知识点(部分,无序)

文章详细介绍了JavaScript中的匿名函数定义及原型链继承的几种方式,包括原型链继承、借用构造函数继承、组合继承和原型式继承,分析了各自的优缺点。同时,讨论了函数提升和变量提升的概念。此外,还探讨了类的声明、类表达式以及类的修饰符作用。最后,对比了xhr与fetch进行网络请求的区别和fetch的兼容性问题。
摘要由CSDN通过智能技术生成

1.定义匿名函数:

<script type="text/javascript">

var f = function (name){

document.writeln('匿名函数<br/>');

document.writeln('你好' + name) ;

};

f('china') ;

</script>

2.继承:

1)原型链继承:

让一个构造函数的原型是另一个类型的实例,那么这个构造函数new出来的实例就具有该实例的属性。

当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

function Parent() {

   this.isShow = true

   this.info = {

       name: "mjy",

       age: 18,

   };

}

Parent.prototype.getInfo = function() {

   console.log(this.info);

   console.log(this.isShow);

}

function Child() {};

Child.prototype = new Parent();

let Child1 = new Child();

Child1.info.gender = "男";

Child1.getInfo(); // {name: 'mjy', age: 18, gender: '男'} ture

let child2 = new Child();

child2.isShow = false

console.log(child2.info.gender) // 男

child2.getInfo(); // {name: 'mjy', age: 18, gender: '男'} false

优点:写法方便简洁,容易理解。

缺点:对象实例共享所有继承的属性和方法。传教子类型实例的时候,不能传递参数,因为这个对象是一次性创建的(没办法定制化)。

2.借用构造函数继承

function Parent(gender) {

  this.info = {

    name: "yhd",

    age: 19,

    gender: gender

  }

}

function Child(gender) {

    Parent.call(this, gender)

}

let child1 = new Child('男');

child1.info.nickname = 'xiaoma'

console.log(child1.info);

let child2 = new Child('女');

console.log(child2.info);

在子类型构造函数的内部调用父类型构造函数;使用 apply()

或 call() 方法将父对象的构造函数绑定在子对象上。

优点:解决了原型链实现继承的不能传参的问题和父类的原

型共享的问题。

缺点:借用构造函数的缺点是方法都在构造函数中定义,因此无法实现函数复用。在父类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。

3.组合继承(经典继承)

function Person(gender) {

  console.log('执行次数');

  this.info = {

    name: "mjy",

    age: 19,

    gender: gender

  }

}

Person.prototype.getInfo = function () {   // 使用原型链继承原型上的属性和方法

  console.log(this.info.name, this.info.age)

}

function Child(gender) {

  Person.call(this, gender) // 使用构造函数法传递参数

}

Child.prototype = new Person()

let child1 = new Child('男');

child1.info.nickname = 'xiaoma'

child1.getInfo()

console.log(child1.info);

let child2 = new Child('女');

console.log(child2.info);

优点: 解决了原型链继承和借用构造函数继承造成的影响。

缺点: 无论在什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数

内部

4.原型式继承

方法一:

借用构造函数在一个函数A内部创建一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的一个新实例。

本质上,函数A是对传入的对象执行了一次浅复制。

function createObject(obj) {

  function Fun() {}

  Fun.prototype = obj

  return new Fun()

}

let person = {

  name: 'mjy',

  age: 18,

  hoby: ['唱', '跳'],

  showName() {

    console.log('my name is:', this.name)

  }

}

let child1 = createObject(person)

child1.name = 'xxxy'

child1.hoby.push('rap')

let child2 = createObject(person)

console.log(child1)

console.log(child2)

console.log(person.hoby) // ['唱', '跳', 'rap']

方法二:Object.create()

Object.create() 是把现有对象的属性,挂到新建对象的原型上,新建对象为空对象

ECMAScript 5通过增加Object.create()方法将原型式继承的概念规范化了。这个方法接收两个参数:作为新对象原型的对象,以及给新对象定义额外属性的对象(第二个可选)。在只有一个参数时,Object.create()与这里的函数A方法效果相同。

let person = {

  name: 'mjy',

  age: 19,

  hoby: ['唱', '跳'],

  showName() {

    console.log('my name is: ', this.name)

  }

}

let child1 = Object.create(person)

child1.name = 'xxt'

child1.hoby.push('rap')

let child2 = Object.create(person)

console.log(child1)//

console.log(child2)//

console.log(person.hoby) // ['唱', '跳', 'rap']

变量提升 函数提升

console.log(a);

var a=6;

简单说就是在js代码执行前引擎会先进行预编译,预编译期间会将变量声明与函数声明提升至其对应作用域的最顶端。

也就是说刚才的代码,js的执行过程其实是这样的:

var a;

console.log(a)

a=6;

js的var关键字把变量声明,提升到了最顶端,然后才去执行剩下的编译代码,这也是最基本的变量提升案例了。

注意:变量提升只提升声明,不提升赋值

function chifan(){

  console.log('我要吃米饭')

}

chifan()

function chifan(){

  console.log('我要吃面')

}

chifan()

变为:

var chifan=function (){

  console.log('我要吃米饭')

}

var chifan=function (){

  console.log('我要吃面')

}

chifan()

chifan()

这就是所谓的js的函数提升,我们使用的是函数声明的方式,所以js会有类似于变量提升的函数提升,与变量提升不同,函数提升不仅仅提升函数声明,而是提升函数整体

var game=function (){

  console.log('玩英雄联盟')

}

game()

var game=function (){

  console.log('玩CSGO')

}

game()

这里并没有用函数声明的方式,而用的是函数表达式的方式,所以并不存在函数整体提升,仅仅也只是声明提升,具体执行过程如下:

var game

var game

game=function (){

  console.log('玩英雄联盟')

}

game()

game=function (){

  console.log('玩CSGO')

}

game()

类的特性

类是用于创建对象的模板。他们用代码封装数据以处理该数据。JS 中的类建立在原型上,但也具有某些语法和语义未与 ES5 类相似语义共享。

实际上,类是“特殊的函数”,就像你能够定义的函数表达式函数声明一样,类语法有两个组成部分:类表达式类声明

类的声明:class Rectangle {

  constructor(height, width) {

    this.height = height;

    this.width = width;

  }

}

函数声明类声明之间的一个重要区别在于,函数声明会提升,类声明不会。你首先需要声明你的类,然后再访问它,否则类似以下的代码将抛出ReferenceError

letp =newRectangle();// ReferenceError

classRectangle{}

类表达式是定义类的另一种方法。类表达式可以命名或不命名。命名类表达式的名称是该类体的局部名称。(不过,可以通过类的 (而不是一个实例的) name 属性来检索它)。

// 未命名/匿名类

let Rectangle = class {

  constructor(height, width) {

    this.height = height;

    this.width = width;

  }

};

console.log(Rectangle.name);

// output: "Rectangle"

// 命名类

let Rectangle = class Rectangle2 {

  constructor(height, width) {

    this.height = height;

    this.width = width;

  }

};

console.log(Rectangle.name);

// 输出:"Rectangle2"

类的修饰符有什么作用

  • public:公开的,谁都能用(默认就是 public
  • private:私有的,仅类自己能使用,子类与外部都不能使用
  • protected:受保护的,仅类和类的子类能使用,外部不能使用
  • readonly:只能读不能写

readonly 只能在 constructor 构造方法初始化时赋值,或者声明时赋值,之后都不能在修改值。

class Person{

  readonly name: string

  // 构造初始化赋值

  constructor(name: string) {

    this.name =  name

  }

}

  • static:静态成员无需实例化,直接通过类名调用

 

网络操作

1)xhr/fetch

1.xhr:在Fetch出现之前我们发送异步请求默认都是通过ajax,底层使用了宿主环境的(XHR)XMLHTTPRequest 对象来实现异步请

求。实现代码如下:

            //获取元素

const result = document.getElementById('result')

//绑定事件

result.addEventListener('mouseover',function(){

//1.创建对象

const xhr = new XMLHttpRequest();

//2.初始化 设置类型与 URL

xhr.open('POST','http://127.0.0.1:8000/server');

//设置请求头

// xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

xhr.setRequestHeader('name','zz');

//3.发送

xhr.send('a=100&b=200&c=300');

// xhr.send('a:100&b:200&c:300');

// xhr.send('123456789');

//4.事件绑定

xhr.onreadystatechange = function(){

//判断

if(xhr.readyState === 4){

if(xhr.status>=200 && xhr.status <300){

//处理服务端返回的结果

result.innerHTML = xhr.response;

}

}

}

})

2.fetch:是一个API 是在ES6出现的 它使用ES6提出的Promise对象 是XMLHttpRequest的替代品 最大的特点就是 通过数据流对象处理数据 可以提高网站性能,它还提供了一个全局 fetch()方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。

fetch('http://example.com/movies.json')

  .then(function(response) {

    return response

  })

  .then(function(response) {

    console.log(response);

  });

但是:

1.fetch是有兼容问题的

IE系列是完全不支持的,主流浏览器的早起版本也不支持,所以

如果在项目中使用需要做兼容方案处理。

2.fetch 不管请求处理成功还是失败,都会触发promise的resolve状态回掉。这个和传统的ajax 框架是有点区别的。fetch只有当网络故障导致请求发送失败或者跨域的时候才会触发reject的逻辑。我们可以通过response 对象的ok是否是true来判断是否是真正的成功。

3.fetch配置请求是否携带cookie和接受服务端写入cookie是通过设

置credentials

fetch('/users.json', {

    method: 'POST',

    body: JSON.stringify({

        email: 'huang@163.com'

        name: 'jim'

    })

}).then(function() { /* 处理响应 */ });

url参数是必须要填写的,option可选,设置fetch调用时的Request对象,如method、headers等

比较常用的Request对象有:

  • method - 支持 GET, POST, PUT, DELETE, HEAD
  • url - 请求的 URL
  • headers - 对应的 Headers 对象
  • body - 请求参数(JSON.stringify 过的字符串或’name=jim\u0026age=22’ 格式)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值