• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

JS高级之面试必须知道的几个点_js

javascript 搞代码 7年前 (2018-06-21) 145次浏览 已收录 0个评论
文章目录[隐藏]

前言

这段时间突然发现js原生好多东西都忘记了,但有些东西确实很重要,所以又重新再梳理一次。主要有函数的3种定义方法,ES5函数this指向,call与appl用法,JS常见的4种设计模式,原型链,原型链和继承的方式(ES5和ES6)

JS高级之面试必须知道的几个点_js

1.函数的3种定义方法

1.1 函数声明

 //ES5 function getSum(){} function (){}//匿名函数 //ES6 ()=>{}//如果{}内容只有一行{}和return关键字可省, 

1.2 函数表达式(函数字面量)

 //ES5 var sum=function getSum(){} //ES6 let sum=()=>{}//如果{}内容只有一行{}和return关键字可省,

1.3 构造函数

 var sum=new GetSum(num1,num2) 

1.4 三种方法的对比

1.函数声明有预解析,而且函数声明的优先级高于变量;
2.使用Function构造函数定义函数的方式是一个函数表达式,这种方式会导致解析两次代码,影响性能。第一次解析常规的JavaScript代码,第二次解析传入构造函数的字符串

2.ES5中函数的4种调用

在ES5中函数内容的this指向和调用方法有关

2.1 函数调用模式

包括函数名()和匿名函数调用,this指向window

  function getSum() {     console.log(this) //window  }  getSum()    (function() {     console.log(this) //window  })()    var getSum=function() {     console.log(this) //window  }  getSum()

2.2 方法调用

对象.方法名(),this指向对象

 var objList = {    name: 'methods',    getSum: function() {      console.log(this) //objList对象    } } objList.getSum()

2.3 构造器调用

new 构造函数名(),this指向构造函数

 function Person() {   console.log(this); //指向构造函数Person } var personOne = new Person(); 

2.4 间接调用

利用call和apply来实现,this就是call和apply对应的第一个参数,如果不传值或者第一个值为null,undefined时this指向window

 function foo() {    console.log(this); } foo.apply('我是apply改变的this值');//我是apply改变的this值 foo.call('我是call改变的this值');//我是call改变的this值

3.ES6中函数的调用

箭头函数不可以当作构造函数使用,也就是不能用new命令实例化一个对象,否则会抛出一个错误
箭头函数的this是和定义时有关和调用无关
调用就是函数调用模式

 (() => {    console.log(this)//window })()  let arrowFun = () => {   console.log(this)//window } arrowFun()  let arrowObj = {   arrFun: function() {    (() => {      console.log(this)//arrowObj    })()    }  }  arrowObj.arrFun();  

4.call,apply和bind

1.IE5之前不支持call和apply,bind是ES5出来的;
2.call和apply可以调用函数,改变this,实现继承和借用别的对象的方法;

4.1 call和apply定义

调用方法,用一个对象替换掉另一个对象(this)
对象.call(新this对象,实参1,实参2,实参3…..)

http://www.gaodaima.com/54599.htmlJS高级之面试必须知道的几个点_js

对象.apply(新this对象,[实参1,实参2,实参3…..])

4.2 call和apply用法

1.间接调用函数,改变作用域的this值
2.劫持其他对象的方法

 var foo = {   name:"张三",   logName:function(){     console.log(this.name);   } } var bar={   name:"李四" }; foo.logName.call(bar);//李四 实质是call改变了foo的this指向为bar,并调用该函数 

3.两个函数实现继承

 function Animal(name){      this.name = name;      this.showName = function(){        console.log(this.name);      }    }    function Cat(name){     Animal.call(this, name);   }     var cat = new Cat("Black Cat");    cat.showName(); //Black Cat 

4.为类数组(arguments和nodeList)添加数组方法push,pop

 (function(){   Array.prototype.push.call(arguments,'王五');   console.log(arguments);//['张三','李四','王五'] })('张三','李四') 

5.合并数组

 let arr1=[1,2,3];  let arr2=[4,5,6];  Array.prototype.push.apply(arr1,arr2); //将arr2合并到了arr1中 

6.求数组最大值

 Math.max.apply(null,arr) 

7.判断字符类型

 Object.prototype.toString.call({})

4.3 bind

bind是function的一个函数扩展方法,bind以后代码重新绑定了func内部的this指向,不会调用方法,不兼容IE8

 var name = '李四'  var foo = {    name: "张三",    logName: function(age) {    console.log(this.name, age);    }  }  var fooNew = foo.logName;  var fooNewBind = foo.logName.bind(foo);  fooNew(10)//李四,10  fooNewBind(11)//张三,11  因为bind改变了fooNewBind里面的this指向

5.JS常见的四种设计模式

5.1 工厂模式

简单的工厂模式可以理解为解决多个相似的问题;

 function CreatePerson(name,age,sex) {     var obj = new Object();     obj.name = name;     obj.age = age;     obj.sex = sex;     obj.sayName = function(){         return this.name;     }     return obj; } var p1 = new CreatePerson("longen",'28','男'); var p2 = new CreatePerson("tugenhua",'27','女'); console.log(p1.name); // longen console.log(p1.age);  // 28 console.log(p1.sex);  // 男 console.log(p1.sayName()); // longen  console.log(p2.name);  // tugenhua console.log(p2.age);   // 27 console.log(p2.sex);   // 女 console.log(p2.sayName()); // tugenhua  

5.2单例模式

只能被实例化(构造函数给实例添加属性与方法)一次

 // 单体模式 var Singleton = function(name){     this.name = name; }; Singleton.prototype.getName = function(){     return this.name; } // 获取实例对象 var getInstance = (function() {     var instance = null;     return function(name) {         if(!instance) {//相当于一个一次性阀门,只能实例化一次             instance = new Singleton(name);         }         return instance;     } })(); // 测试单体模式的实例,所以a===b var a = getInstance("aa"); var b = getInstance("bb");   

5.3 沙箱模式

将一些函数放到自执行函数里面,但要用闭包暴露接口,用变量接收暴露的接口,再调用里面的值,否则无法使用里面的值

 let sandboxModel=(function(){     function sayName(){};     function sayAge(){};     return{         sayName:sayName,         sayAge:sayAge     } })() 

5.4 发布者订阅模式

就例如如我们关注了某一个公众号,然后他对应的有新的消息就会给你推送,

 //发布者与订阅模式     var shoeObj = {}; // 定义发布者     shoeObj.list = []; // 缓存列表 存放订阅者回调函数      // 增加订阅者     shoeObj.listen = function(fn) {         shoeObj.list.push(fn); // 订阅消息添加到缓存列表     }      // 发布消息     shoeObj.trigger = function() {             for (var i = 0, fn; fn = this.list[i++];) {                 fn.apply(this, arguments);//第一个参数只是改变fn的this,             }         }      // 小红订阅如下消息     shoeObj.listen(function(color, size) {         console.log("颜色是:" + color);         console.log("尺码是:" + size);     });      // 小花订阅如下消息     shoeObj.listen(function(color, size) {         console.log("再次打印颜色是:" + color);         console.log("再次打印尺码是:" + size);     });     shoeObj.trigger("红色", 40);     shoeObj.trigger("黑色", 42);   

代码实现逻辑是用数组存贮订阅者, 发布者回调函数里面通知的方式是遍历订阅者数组,并将发布者内容传入订阅者数组

更多设计模式请戳:javascript常用的设计模式详解

6.原型链

6.1 定义

对象继承属性的一个链条

6.2构造函数,实例与原型对象的关系

JS高级之面试必须知道的几个点_js

 var Person = function (name) { this.name = name; }//person是构造函数 var o3personTwo = new Person('personTwo')//personTwo是实例

JS高级之面试必须知道的几个点_js

原型对象都有一个默认的constructor属性指向构造函数

6.3 创建实例的方法

1.字面量

 let obj={'name':'张三'} 

2.Object构造函数创建

 let Obj=new Object() Obj.name='张三'

3.使用工厂模式创建对象

 function createPerson(name){  var o = new Object();  o.name = name;  };  return o;  } var person1 = createPerson('张三');

4.使用构造函数创建对象

 function Person(name){  this.name = name; } var person1 = new Person('张三');

6.4 new运算符

1.创了一个新对象;
2.this指向构造函数;
3.构造函数有返回,会替换new出来的对象,如果没有就是new出来的对象
4.手动封装一个new运算符

 var new2 = function (func) {     var o = Object.create(func.prototype);    //创建对象     var k = func.call(o);             //改变this指向,把结果付给k     if (typeof k === 'object') {         //判断k的类型是不是对象         return k;                  //是,返回k     } else {         return o;                  //不是返回返回构造函数的执行结果     } }  

更多详情:详谈JavaScript原型链

6.5 对象的原型链

JS高级之面试必须知道的几个点_js

7.继承的方式

JS是一门弱类型动态语言,封装和继承是他的两大特性

7.1原型链继承

将父类的实例作为子类的原型
1.代码实现
定义父类:

 // 定义一个动物类 function Animal (name) {   // 属性   this.name = name || 'Animal';   // 实例方法   this.sleep = function(){     console.log(this.name + '正在睡觉!');   } } // 原型方法 Animal.prototype.eat = function(food) {   console.log(this.name + '正在吃:' + food); }; 

子类:

 function Cat(){  } Cat.prototype = new Animal(); Cat.prototype.name = 'cat';  // Test Code var cat = new Cat(); console.log(cat.name);//cat console.log(cat.eat('fish'));//cat正在吃:fish  undefined console.log(cat.sleep());//cat正在睡觉! undefined console.log(cat instanceof Animal); //true  console.log(cat instanceof Cat); //true 

2.优缺点
简单易于实现,但是要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,无法实现多继承

7.2 构造继承

实质是利用call来改变Cat中的this指向
1.代码实现
子类:

 function Cat(name){   Animal.call(this);   this.name = name || 'Tom'; }

2.优缺点
可以实现多继承,不能继承原型属性/方法

7.3 实例继承

为父类实例添加新特性,作为子类实例返回
1.代码实现
子类

 function Cat(name){   var instance = new Animal();   instance.name = name || 'Tom';   return instance; }

2.优缺点
不限制调用方式,但不能实现多继承

7.4 拷贝继承

将父类的属性和方法拷贝一份到子类中
1.子类:

 function Cat(name){   var animal = new Animal();   for(var p in animal){     Cat.prototype[p] = animal[p];   }   Cat.prototype.name = name || 'Tom'; }

2.优缺点
支持多继承,但是效率低占用内存

7.5 组合继承

通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
1.子类:

 function Cat(name){   Animal.call(this);   this.name = name || 'Tom'; } Cat.prototype = new Animal(); Cat.prototype.constructor = Cat;

7.6 寄生组合继承

 function Cat(name){   Animal.call(this);   this.name = name || 'Tom'; } (function(){   // 创建一个没有实例方法的类   var Super = function(){};   Super.prototype = Animal.prototype;   //将实例作为子类的原型   Cat.prototype = new Super(); })(); 

7.7 ES6的extends继承

ES6 的继承机制是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this,链接描述

 class ColorPoint extends Point {   constructor(x, y, color) {     super(x, y); // 调用父类的constructor(x, y)     this.color = color;   }    toString() {     return this.color + ' ' + super.toString(); // 调用父类的toString()   } }    

更多详情请戳:JS继承的实现方式

欢迎大家阅读《JS高级之面试必须知道的几个点_js》,跪求各位点评,若觉得好的话请收藏本文,by 搞代码


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:JS高级之面试必须知道的几个点_js

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址