`
35687638
  • 浏览: 9952 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

JavaScript面试必须懂的问题

阅读更多

一. JavaScript中的对象.
JavaScript中的Object是一组数据的key-value的集合, 有点类似于 Java中的HashMap, 所有这些数据都是Object里的property. 通常情况下, JavaScript中建立一个对象用”new”加上constructor function来实现. 如new Date(), new Object()等.
var book = new Object();
book.name = "JavaScript is Cool";
book.author = "tom";
book.pages = 514;


上面例子中的name和page就是名为book的对象中的property. 我们可以用delete来删除Object中的 property: “delete book.name;”. 除了Object, Date等buildin的对象外, 我们可以写自己的 constructor function, 然后使用new就可以建立自己的对象. 如上面的book可以写成:
function Book (name, author, page) {
 this.name = name;
 this.author = author;
 this.page = page;
}
var abook = new Book("JavaScript is Cool", "tom", 514);


二. function的用法
在 JavaScript中, function是一种数据类型, 所有的function都是从buildin的Function object 衍生的对象. 所以在JavaScript 中function可以作为参数传递, 可以作为Object的property, 也可以当作函数返回值. function在JavaScript中有两种用法, 一种是当作constructor, 前面加上new keyword用来建立对象. 一种是当作method, 为其他对象调用.
注意function和method在中文里的意思相当, 在有些语言里也可以通用. 但是在 JavaScript中, 它们还是有所区别的. function本身是是一个对象, 而当作为一个方法他属于一个对象时, 就成为了一个这个对象的 method, 相当于一个对象种的属性. 也就是说method是相对于一个对象而言的, function在某些情况下成为了一个对象的 method.
function Book(name, author, page) {
 this.name = name;
 this.author = author;
 this.page = page;
 this.getReader = Book_getReader;
}
 
function Book_getReader() {
 //....
}


上面的例子种, function Book_getReader()就成为了Book的一个名为getReader的method. call()和 apply()是Function object 的两个方法, 它们也可以使一个function作为另一个对象的method来调用用. call()和apply()都需要参数, 而第一个参数就是调用对象, 也就是当function内部出现this时, this所指的对象. call()和apply()的区别在于call()可以传递任意长度参数, 只要第一个参数时调用对象. 而apply只接受两个参数, 需要将除调用对象外的所有参数放入一个数组中. 即:

function getBooksWithSameAuthor(form, to) {
 var name = this.author;
 var books = ...
 //get books written by name and from year "from"  to year "to"
 return books;
}
 
var abook = new Book("JavaScript is Cool", "tom", 514);
var books = getBooksWithSameAuthor.call(abook, 1990, 2005);
或
var books = getBooksWithSameAuthor.apply(abook, [1990, 2005]);


当一个function不作为一个对象的method时, JavaScript会认为它是属于一个Globle Object对象的method, 这个 Globle Object在Browser中就是window类. 所以从这个角度来说, function和method又可以统一起来了.
Function object 还有一个非常重要的property: prototype. 它是一个predefined的prototype object. 当一个 Function用作对象的constructor时, protptype property将发挥作用,中文翻译叫原型. JavaScript的新对象就是通过function的原型来建立的. 同时我们还可以利用prototype来动态的向对象中添加属性, 如:

function Book (name, author, page) {
 this.name = name;
 this.author = author;
 this.page = page;
}
var abook = new Book("JavaScript is Cool", "tom", 514);
 
Book.prototype.getInfo = getInfo;
function getInfo() {
 return this.name + " written by " + this.author + " with " + this.page + " pages";
}
 
alert(abook.getInfo());


这里有一个例子, 用prototype方法来实现callback:

Function.prototype.andThen=function(g) {
  var f=this;
  return function() {
    f();g();
  }
};
 
function Manager() {
  this.callback=function () {}; // do nothing
  this.registerCallback=function(callbackFunction) {
    this.callback=(this.callback).andThen(callbackFunction);
  }
}
 
var manager=new Manager();
manager.registerCallback(sayHi);
manager.registerCallback(sayBye);
manager.callback();


三. JavaScript中的OO
JavaScript中的对象是一个属性和方法的集合. JavaScript也有对应于Java的Class和Instance的概念.我们可以把JavaScript中定义的
function(Function类的子类)看作是Class, 而利用这个function构造的对象看是Instance. 对应于Java的Instance Property, Instance
Method, Class(static) property, Class Method, JavaScript都可以实现.
1. Instance Property
Instance Property就是cuntructor function中定义的property, 对于每一个instance都会有一份copy.
2. Class property
Class Property其实是cunstructor function作为对象本身所具有的属性(和Java不一样, Java中method不是数据, 更不是对象).
3. Instance Method
Instance Method 是指属于某一对象的method, 方法内的this代表这个method从属的对象, 注意虽然是Instance Method, 并不是每一个 Instance都有一个此方法的copy, 所有Instance 共享一个method.
4. Class Method
Class Method 同样可以理解为constructor function作为对象自己具有的方法, 和由这个constructor建立的对象没有直接联系. 所以 Class Method方法里使用this会产生混淆. 因为这个this指的不是期望操作的对象, 而是一个 Function Object(constructor).
下面的例子定义了一个复数的对象, 包含有上述四种域, 值得仔细看看:
/*
 
 * Complex.js:
 
 * This file defines a Complex class to represent complex numbers.
 
 * Recall that a complex number is the sum of a real number and an
 
 * imaginary number and that the imaginary number i is the
 
 * square root of -1.
 
 */
 
 
/*
 
 * The first step in defining a class is defining the constructor
 
 * function of the class. This constructor should initialize any
 
 * instance properties of the object. These are the essential
 
 * "state variables" that make each instance of the class different.
 
 */
 
function Complex(real, imaginary) {
 
    this.x = real;       // The real part of the number
 
    this.y = imaginary;  // The imaginary part of the number
 
}
 
 
/*
 
 * The second step in defining a class is defining its instance
 
 * methods (and possibly other properties) in the prototype object
 
 * of the constructor. Any properties defined in this object will
 
 * be inherited by all instances of the class. Note that instance
 
 * methods operate implicitly on the this keyword. For many methods,
 
 * no other arguments are needed.
 
 */
 
 
// Return the magnitude of a complex number. This is defined
 
// as its distance from the origin (0,0) of the complex plane.
 
Complex.prototype.magnitude = function(  ) {
 
    return Math.sqrt(this.x*this.x + this.y*this.y);
 
};
 
 
// Return a complex number that is the negative of this one.
 
Complex.prototype.negative = function(  ) {
 
    return new Complex(-this.x, -this.y);
 
};
 
 
//  Convert a Complex object to a string in a useful way.
 
//  This is invoked when a Complex object is used as a string.
 
Complex.prototype.toString = function(  ) {
 
    return "{" + this.x + "," + this.y + "}";
 
};
 
 
// Return the real portion of a complex number. This function
 
// is invoked when a Complex object is treated as a primitive value.
 
Complex.prototype.valueOf = function(  ) { return this.x; }
 
 
/*
 
 * The third step in defining a class is to define class methods,
 
 * constants, and any needed class properties as properties of the
 
 * constructor function itself (instead of as properties of the
 
 * prototype object of the constructor). Note that class methods
 
 * do not use the this keyword: they operate only on their arguments.
 
 */
 
 
// Add two complex numbers and return the result.
 
Complex.add = function (a, b) {
 
    return new Complex(a.x + b.x, a.y + b.y);
 
};
 
 
// Subtract one complex number from another.
 
Complex.subtract = function (a, b) {
 
    return new Complex(a.x - b.x, a.y - b.y);
 
};
 
 
// Multiply two complex numbers and return the product.
 
Complex.multiply = function(a, b) {
 
    return new Complex(a.x * b.x - a.y * b.y,
 
                       a.x * b.y + a.y * b.x);
 
};
 
 
// Here are some useful predefined complex numbers.
 
// They are defined as class properties, where they can be used as
 
// "constants." (Note, though, that they are not actually read-only.)
 
Complex.zero = new Complex(0,0);
 
Complex.one = new Complex(1,0);
 
Complex.i = new Complex(0,1);

四. 对象的继承
JavaScript有多种方式模拟继承.
1. 利用function:
function superClass() {
  this.bye = superBye;
  this.hello = superHello;
}
 
function subClass() {
  this.inheritFrom = superClass;
  this.inheritFrom();
  this.bye = subBye;
}

或者:
function subClass() {
  superClass.call(this);
}


先定义subClass的inheritFrom方法, 再调用这个方法(方法名称并不重要), 或者直接使用Function Object 的 call 方法将this做参数, 都可以模拟实现从superClass的继承. 注意调用superClass时的this指向. 这个方法就是在执行subClass的cunstructor function时, 先执行supperClass的cunstructor function.这个方法的缺点在于子类仅仅是在自己的构造函数中, 将this作为参数调用了父类的构造函数, 将构造函数赋予父类的所有域赋予子类. 所以, 任何父类在构造函数之外(通过prototype)定义的域, 子类都无法继承. 而且子类的构造函数一定要在定义自己的域之前调用父类的构造函数, 免得子类的定义被父类覆盖. 使用这种方法子类也尽量不要使用prototype来定义子类的域, 因为prototype的定义在子类new的之后就执行, 所以它一定会在调用父类构造函数前, 同样会有被父类的定义覆盖的危险.
2. 利用prototype:
function superClass() {
  this.bye = superBye;
  this.hello = superHello;
}
 
function subClass() {
  this.bye = subBye;
}
subClass.prototype = new superClass();
subClass.prototype.constructor = superClass;


这里将一个superClass的实例设置成subclass的原型:protytype, 由于new superClass实例一定会调用父类 prototype定义的所有域, 所以这种方法避免了上一种方法的一个问题, 父类可以通过prototype来描述域. 可以实现从 superClass的继承. 而这个方法也有缺点, 由于子类的peototype已经是父类的实例(Object实例), 不能再被实例化, 所以 new子类实例的时候, 父类的所有非基本数据类型(见JavaScript数据类型)都将是reference copy而非数据copy. 简单说就是所有的父类域在子类中虽然存在, 但看起来就像Java中的static域一样在子类间share.被一个子类改变, 所有子类都会改变.
注意这里的最后一句, 改变了子类prototype中的constructor属性. 它对子类使用没有影响, 仅仅是为了在调用instanceOf方法时它使得子类实例返回subClass.
3. Parasitic Inheritance (寄生继承)
function superClass() {
  this.bye = superBye;
  this.hello = superHello;
}
 
function subClass() {
  this.base = new supperClass();
  base.sayBye = subBye;
  return base;
}


这种继承其实是一种扩展, 因为在调用instanceOf时, 子类会返回父类名称, 它的好处在于在构造函数继承的基础上解放了父类, 父类可以使用 prototype定义自己的域, 但是子类仍然不建议使用prototype, 以免被父类覆盖. 为了可以使子类的instanceof返回正确类型, 我们可以再改进一下:

function subClass() {
  this.base = new supperClass();
  for ( var key in this.base ) {
      if ( !this[key] ) {
          this[key] = this.base[key];
      } 
  }
 
  this.sayBye = subBye;
}


将所有的父类域拷贝给子类一份, 不再返回父类, instanceof子类实例时就可以返回正确类型.
五. this的用法
通常情况下, this代表的是前面提到的Globle Object.也就是Browser环境时的window Object. 当function作为某一对象的 method 时, this 代表这个 function 所属的 object. 下面这段代码有格错误, 涉及到this的使用:

function Employee(a) {
  this.name = a;
}
 
function init(){
  John = Employee("Johnson");
  alert(John.name);
}

在init()中我们少了一个new keyword. 于是这个代码就会报错, 因为Browser把Employee当作是window obect的一个method, 里面的this指的就是window object. init()应该改为:

function init(){
  John = new Employee("Johnson");
  alert(John.name);
}

同时我们也可以将Employee的constructor函数修改, 防止类似的错误:

function Employee(a) {
  if (!(this instanceof Employee)) return new Employee(a);
  this.name = a;
}


这样,我们即使使用原来的init()方法, 也不会报错了.
六. Array in JavaScript
Array和Object本质上是一样的, 只是Array需要由index来索引它其中的属性. index为>=0的整数.
Array有一系列buildin的方法:
1. jion() 将array中的所有element以string的形式连在一起:

  var a = [1,2,3];
  s = a.join();      // s == "1,2,3"
  s = a.join(": ");  // s == "1: 2: 3"


2. reverse() 将Array的element顺数颠倒

  var a = [1,2,3];
  a.reverse();
  s = a.join(); // s == "3,2,1"


3. sort() 排序, 默认按字母顺序排序case sensitive, 可以自定义排序方式.

  var a = [111,4,33,2];
  a.sort();  // a == [111,2,33,4]
 
  a.sort(function(a,b) { // a == [2,4,33,111]
       return a-b;       // Returns < 0, 0, or > 0
    });


4. concat()连接多个Array

  var a = [1,2,3];
  a.concat(4,5);          // return [1,2,3,4,5]
  a.concat([4,5]);        // return [1,2,3,4,5]
  a.concat([4,5], [6,7])  // return [1,2,3,4,5,6,7]  
  a.concat(4,[5,[6,7]]);  // return [1,2,3,4,5,6,7]

5. slice() 返回Array的切片, 原Array不变.

  var a = [1,2,3,4,5];
  a.slice(0,3);    // Returns [1,2,3]
  a.slice(3);      // Returns [4,5]
  a.slice(1,-1);   // Returns [2,3,4], -1 means the last index of the array
  a.slice(-3,-2);  // Returns [3], from the third last index to the second last index


6. splice 向一个Array中添加或删除element. 第一个参数表示位置, 第二个参数表示删除长度, 后面任意长的参数表示在1删除位置添加的elements.

  var a = [1,2,3,4,5,6,7,8];
  a.splice(4);    // Returns [5,6,7,8]; a is [1,2,3,4]
  a.splice(1,2);  // Returns [2,3]; a is [1,4]
  a.splice(1,1);  // Returns [4]; a is [1] 
 
  var a = [1,2,3,4,5];
  a.splice(2,0,'a','b');  // Returns []; a is [1,2,'a','b',3,4,5]
  a.splice(2,2,[1,2],3);  // Returns ['a','b']; a is [1,2,[1,2],3,3,4,5]


7. push() and pop() 向Array末尾添加或删除element
8. unshift() and shift() 向Array的开头添加或删除eleme
分享到:
评论

相关推荐

    参加JavaScript面试,必须搞懂的问题(推荐)

    总结起来,理解和熟练掌握JavaScript中的对象和函数,包括它们的创建、属性操作、方法调用以及`call()`和`apply()`的使用,对于参加JavaScript面试至关重要。这些基础知识是JavaScript开发者日常工作中必不可少的...

    javascript个人学习总结:包括数据结构与算法,前端工程化等方面,助你快速入门

    一次弄懂Event Loop(彻底解决此类面试问题) 浏览器与Node的事件循环(Event Loop)有何区别? 笔试题——JavaScript事件循环机制(event loop、macrotask、microtask) 五.异步编程 理解 JavaScript 的 async/await ...

    前端大厂最新面试题-万字面试干货.docx

    参考链接中的文章提供了丰富的面试准备资源,包括中高级前端面试秘籍、面试经验分享、JavaScript手写代码技巧等,可帮助你更全面地准备面试。在面试过程中,清晰阐述项目经验,展现你的思考和解决问题的能力,将是...

    前端面试-腾讯

    - 如果遇到不懂的问题,可以请求面试官进一步解释。 5. **准备问题** - 提前准备几个针对公司的技术相关问题,表现出对公司文化和职位的兴趣。 - 例如:“团队如何进行技术选型?”、“日常工作中有哪些技术难题...

    java面试题以及技巧

    ├─JavaScript 面试题 │ 新建 文本文档.txt │ ├─Java基础 │ └─SCJP │ │ 2006_02_01_SCWJD_EXAM.pdf │ │ Assertions.doc │ │ Collections.doc │ │ Desktop_.ini │ │ Fundamentals of the Java ...

    考试类精品--️每天花5分钟的时间,弄懂一道面试题 or Js小知识 来鞭策自己学习思考,每天进步一点,流年笑掷,未.zip

    【标签】为空,意味着没有提供特定的分类标签,可能这份资料包含了广泛的JavaScript基础知识或者面试常见问题,覆盖了Js语言的多个方面,如变量、数据类型、函数、对象、数组、控制流、错误处理、DOM操作等。...

    java面试题及技巧4

    ├─JavaScript 面试题 │ 新建 文本文档.txt │ ├─Java基础 │ └─SCJP │ │ 2006_02_01_SCWJD_EXAM.pdf │ │ Assertions.doc │ │ Collections.doc │ │ Desktop_.ini │ │ Fundamentals of the Java ...

    Javascript面试经典套路reduce函数查重

    今天在偶然间查看到了一段代码,代码使用了很短的篇幅完成了字符串统计相同字符次数这个经典面试题,其中用到了reduce这个方法,网上查了查,没有查到什么有价值的东西,导致浪费了我一些时间才看懂,现将我的思路...

    java面试重点总结

    ### Java面试重点总结 #### 一、反射机制 **反射机制**是Java中一项非常重要的技术,它允许程序在运行时动态地获取类的信息并直接操作这些信息。这对于框架开发和扩展性要求高的系统非常重要。 - **应用场景**: ...

    彻底弄懂 JavaScript 执行机制

    不论你是javascript新手还是老鸟,不论是面试求职,还是日常开发工作,我们经常会遇到这样的情况:给定的几行代码,我们需要知道其输出内容和顺序。因为javascript是一门单线程语言,所以我们可以得出结论: ...

    java面试题目与技巧1

    ├─JavaScript 面试题 │ 新建 文本文档.txt │ ├─Java基础 │ └─SCJP │ │ 2006_02_01_SCWJD_EXAM.pdf │ │ Assertions.doc │ │ Collections.doc │ │ Desktop_.ini │ │ Fundamentals of the Java ...

    java面试题及技巧3

    ├─JavaScript 面试题 │ 新建 文本文档.txt │ ├─Java基础 │ └─SCJP │ │ 2006_02_01_SCWJD_EXAM.pdf │ │ Assertions.doc │ │ Collections.doc │ │ Desktop_.ini │ │ Fundamentals of the Java ...

    java面试题以及技巧6

    ├─JavaScript 面试题 │ 新建 文本文档.txt │ ├─Java基础 │ └─SCJP │ │ 2006_02_01_SCWJD_EXAM.pdf │ │ Assertions.doc │ │ Collections.doc │ │ Desktop_.ini │ │ Fundamentals of the Java ...

    2022年程序员面试的自我介绍范文汇编十篇.pdf,这是一份不错的文件

    7. **职业目标**:清晰地表达你的职业规划,希望成为一名既懂技术又懂业务的复合型人才,这显示了你的长远视野和职业追求。 8. **实习经历**:分享实习经历,如在浪潮软件园的实习,可以体现你将理论知识转化为实际...

    BLOG:我的前端学习经历,汇总html、css、javascript等知识点以及面试相关,每周定期更新,喜欢请Star,共同交流进步

    #####目前坐标:辽宁大连 ...JavaScript CSS HTML 备忘录 面试 转—前端开发面试题 ####优秀博客 张云龙 玉伯 Heero ####优秀教程 React 入门实例教程 一看就懂的ReactJs入门教程-精华版 AngularJS中文网

    自己搜集到的一些面试题(并不完善,慎下)

    本篇文章将对 JavaScript 相关的知识点进行总结,涵盖了面试题、ChatGPT 在前端开发中的应用、HTML 语义化、script 标签中的 defer 和 async、浏览器地址栏输入 URL 到请求返回的过程、Promise 的输出结果等多个方面...

    2022年程序员面试的自我介绍模板汇编七篇.pdf,这是一份不错的文件

    最后,在职业规划方面,我希望自己能够成为一名既懂技术又懂业务的复合型人才。我认为,理解业务需求和技术实现之间的桥梁,是一名优秀的软件开发人员所必备的素质。因此,我将持续学习,不断提高自己,以期在职业...

    11-总结.md

    针对前端开发面试,本章将通过一系列的面试题来展开讲解,帮助应聘者掌握分析问题和解决问题的技巧。在分析和解决问题的过程中,有几个关键点是需要考察的: 首先,考察应聘者是否能看懂代码的逻辑。代码逻辑的准确...

    关注基础知识,打造优质前端博客,公众号前端工匠的作者.zip

    欢迎添加我的个人微信frontJS,获取大厂面试题及其答案版权声明本文为博主原创文章,未经博主允许不得转载。掘金博客(全集)sectionFault博客(精华)想加入加入交流群,跟风暴一线大厂的大佬交流学习,先关注「前端...

Global site tag (gtag.js) - Google Analytics