美文网首页
JS考核将要问题摘要

JS考核将要问题摘要

作者: 陈星如_三月 | 来源:发表于2018-11-21 19:10 被阅读41次

undefined和null的区别?

Null类型,代表“空值”,代表一个空对象指针,使用typeof运算得到 “object”,所以你可以认为它是一个特殊的对象值

Undefined类型,当一个声明了一个变量未初始化时,得到的就是undefined 

区分空指针对象  空的对象 和    未初始化的变量  空的变量


NAN的含义用法

即非数值(Not a Number)是一个特殊的值

这个数值表示本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误了)

任何与NaN进行运算的结果均会为NaN,NaN与自身不相等(NaN不与任何值相等)

判断这个是不是NaN用isNaN()函数,是的话返回true

有三个函数可以把非数值转换成数值:Number()、parseInt()和parseFloat()。Number()是转换型函数,可以用于任何数据类型,而另外两个则专门用于把字符串转换成数值 引申至文2018-11-20


阻止a标签的跳转的方法

*1  href="javascript:void(0)"  或 href="javascript:;"伪协议 不提倡使用

javascript中void是一个操作符,该操作符指定要计算一个表达式但是不返回值

*2 onclick="return false"

*3 href="#" 最常用,跳转到页面顶端默认为#top,跟锚点有些类似


布尔值判断为false的六种值

空字符串 /  null  /  undefined  / false / 0 / NaN


六种数据类型

值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、对象(Object),Symbol。

引用数据类型:对象(Object)、数组(Array)、函数(Function)。


form表单

form的action属性就是提交数据的url地址

method属性可以指定是GET或POST

两种的一个区别是GET会直接把数据附加在url的后面,而POST发送的数据放置在http包中不会显示在网址上


卫语句的定义用法

卫语句就是把复杂的条件表达式拆分成多个条件表达式,比如一个很复杂的表达式,嵌套了好几层的if - then-else语句,转换为多个if语句,实现它的逻辑,这多条的if语句就是卫语句

有时候条件式可能出现在嵌套n次才能真正执行,其他分支只是简单报错返回的情况,对于这种情况,应该单独检查报错返回的分支,当条件为真时立即返回,这样的单独检查就是卫语句(guard clauses).卫语句可以把我们的视线从异常处理中解放出来,集中精力到正常处理的代码中。


异步加载Js

js加载的缺点:加载工具方法没必要阻塞文档,过多js加载会影响页面效率,一旦网速不好,那么整个网站将等待js加载而不进行后续渲染等工作。 有些工具方法需要按需加载,用到再加载,不用不加载

  默认正常模式下下,JS是同步加载的,即优先加载JS,只有当JS文件下载完,dom和css才开始加载,当某些时候我们需要JS异步加载,我们可以通过以下方式来设置异步加载,不同情况下选取不同方式即可

1.defer:defer

JS异步下载,dom结构解析完(标签 + 样式(内容不一定下载完))才异步执行

仅IE能用

内部JS也能用该属性

异步加载js不允许使用document.write,因为document.write会清除文档流,js标签还未加载就会被清除

document.write()可用于初始化页面

2.(h5)async:async(asynchronous)    ajax(asynchronous javascript and XML)

JS异步加载,加载完毕后立刻异步执行

IE8及以下不兼容

内部JS不能用该属性

3.除了以上两种方法,还有一种兼容自己封装的异步加载方式,即动态添加script标签也能实现异步加载。


Js循环有几种方式

1、for 循环

2、for in 循环

3、while 循环

4、do while 循环

5、Array forEach 循环

6、Array map()方法

7、Array filter() 方法

8、Array some() 方法

9、Array every() 方法。。。。。


声明变量几种变量方式

三种  var  const  let 

区别:

var正常普通

let声明的变量在{}中使用,变量的作用域限制在块级域中

const用于修饰常量,定义的变量不可修改,而且必须初始化,声明位置不限(通常声明在js开头),与java类的final关键字性质一样


关于闭包

准确来说,闭包是基于正常的垃圾回收处理机制下的。也就是说,一般情况一个函数(函数作用域)执行完毕,里面声明的变量会全部释放,被垃圾回收器回收。但闭包利用一个技巧,让作用域里面的变量,在函数执行完之后依旧保存没有被垃圾回收处理掉。

优缺点:

优点:设计私有的方法和变量,保护函数内的变量安全;避免全局污染

弊端:闭包有一个非常严重的问题,那就是内存浪费问题,这个内存浪费不仅仅因为它常驻内存,更重要的是,对闭包的使用不当会造成无效内存的产生。改变了js执行机制


回调函数

一. 回调函数的作用

js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作,这时候就需要用到回调函数。

二. 回调函数的解释

因为函数实际上是一种对象,它可以存储在变量中,通过参数传递给另一个函数,在函数内部创建,从函数中返回结果值”,因为函数是内置对象,我们可以将它作为参数传递给另一个函数,到函数中执行,甚至执行后将它返回,它一直被“专业的程序员”看作是一种难懂的技术。

回调函数的英文解释为:

A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.

翻译过来就是:回调函数是一个作为变量传递给另外一个函数的函数,它在主体函数执行完之后执行。

function A有一个参数function B,function B会在function A执行完成之后被调用执行。

字面上的理解:

回调函数就是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。这个过程就叫做回调。

其实也很好理解对吧,回调,回调,就是回头调用的意思。主函数的事先干完,回头再调用传进来的那个函数


么实现一个对象构造器

1.工厂模式

  考虑到在 ECMAScript 中无法创建类,开发人员就发明了一种函数,用函数来封装以特定接口创建对象的细节,如下面的例子所示:

  function createPerson(name,age,job){

    var o = new Object();

    o.name = name;

    o.age = age;

    o.job = job;

    o.sayName = function(){

      alert(this.name);

    }

    return o;

  }

  var person1 = createPerson('Grey',27,'Doctor');

  函数 createPerson()能够根据接受的参数来构建一个包含所有必要信息的 Person 对象。可以无数次地调用这个函数,而每次它都会返回一个包含三个属性一个方法的对象。工厂模式虽然解决了创建\多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。

主要好处就是可以消除对象间的耦合,通过使用工程方法而不是new关键字。将所有实例化的代码集中在一个位置防止代码重复。

  工厂模式解决了重复实例化的问题 ,但还有一个问题,那就是识别问题,因为根本无法 搞清楚他们到底是哪个对象的实例。

2.构造函数模式

  ECMAScript中的构造函数可用来创建特定类型的对象,像Array和Object这样的原生构造函数,在运行时会自动出现在执行环境中。此外,也可以创建自定义的构造函数,从而定义自定义对象的属性和方法。使用构造函数的方法,既解决了重复实例化的问题,又解决了对象识别的问题。例如,可以使用构造函数模式将前面的例子重写如下:

  function Person(name,age,job){

    this.name = name;

    this.age = age;

    this.job = job;

    this.sayName = function(){

      alert(this.name);

    }

  }

  var person1 = new Person("Nicholas", 29, "Software Engineer");

  var person2 = new Person('Grey',27,'Doctor');

  Person()中的代码除了与 createPerson()中相同的部分外,还存在以下不同之处:

 没有显式地创建对象;

 直接将属性和方法赋给了 this 对象;

 没有 return 语句。

 按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头。

  要创建 Person 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下 4个步骤:

(1) 创建一个新对象;

(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);

(3) 执行构造函数中的代码(为这个新对象添加属性);

(4) 返回新对象。

  在前面例子的最后,person1 和 person2 分别保存着 Person 的一个不同的实例。这两个对象都有一个 constructor(构造函数)属性,该属性指向 Person,如下所示。

alert(person1.constructor == Person); //true

alert(person2.constructor == Person); //true

  对象的 constructor 属性最初是用来标识对象类型的。但是,提到检测对象类型,还是 instanceof 操作符要更可靠一些。我们在这个例子中创建的所有对象既是 Object 的实例,同时也是 Person的实例,这一点通过 instanceof 操作符可以得到验证。

alert(person1 instanceof Object); //true

alert(person1 instanceof Person); //true

alert(person2 instanceof Object); //true

alert(person2 instanceof Person); //true

创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型;而这正是构造函数模式胜过工厂模式的地方。

  在这个例子中,person1 和 person2 之所以同时是 Object 的实例,是因为所有对象均继承自 Object.

  前面例子中定义的 Person()函数可以通过下列任何一种方式来调用。

// 当作构造函数使用

var person = new Person("Nicholas", 29, "Software Engineer");

person.sayName(); //"Nicholas"

// 作为普通函数调用

Person("Greg", 27, "Doctor"); // 添加到 window

window.sayName(); //"Greg"

// 在另一个对象的作用域中调用

var o = new Object();

Person.call(o, "Kristen", 25, "Nurse");

o.sayName(); //"Kristen"

  这个例子中的前两行代码展示了构造函数的典型用法,即使用 new 操作符来创建一个新对象。

  接下来的两行代码展示了不使用new操作符调用Person()会出现什么结果:属性和方法都被添加给window对象了。

 当在全局作用域中调用一个函数时,this 对象总是指向 Global 对象(在浏览器中就是 window 对象)。

  因此,在调用完函数之后,可以通过 window 对象来调用 sayName()方法,并且还返回了"Greg"。最后,也可以使用 call()(或者 apply())在某个特殊对象的作用域中调用Person()函数。这里是在对象o 的作用域中调用的,因此调用后o 就拥有了所有属性和sayName()方法。

 3.原型模式

  我们创建的每个函数都有一个 prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。

  如果按字面意思来理解,那么prototype就是通过调用构造函数而创建的那个对象实例的原型对象。使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。换句话说,不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中。例如:

  function Person(){

  }

  Person.prototype.name = 'Nicholas';

  Person.prototype.age = 29;

  Person.prototype.job = 'Software Engineer';

  Person.prototype.sayName = function(){

    alert(this.name);

  }

  var person1 = new Person();

  person1.sayName();//"Nicholas"

  var person2 = new Person();

  person2.sayName(); //"Nicholas"

  alert(person1.sayName == person2.sayName); //true

  在此,我们将 sayName()方法和所有属性直接添加到了 Person 的 prototype 属性中,构造函数变成了空函数。

  即使如此,也仍然可以通过调用构造函数来创建新对象,而且新对象还会具有相同的属性和方法。但与构造函数模式不同的是,新对象的这些属性和方法是由所有实例共享的。换句话说,person1 和 person2 访问的都是同一组属性和同一个 sayName()函数。要理解原型模式的工作原理,必须先理解 ECMAScript 中原型对象的性质。


原型链的了解是否到位

要清楚原型链,首先要弄清楚对象:

普通对象

最普通的对象:有__proto__属性(指向其原型链),没有prototype属性。

原型对象(person.prototype 原型对象还有constructor属性(指向构造函数对象))

函数对象:

凡是通过new Function()创建的都是函数对象。

                          拥有__proto__、prototype属性(指向原型对象)。

                          Function、Object、Array、Date、String、自定义函数

                          特例: Function.prototype(是原型对象,却是函数对象,下面会有解释)

原型对象

        每创建一个函数都会有一个prototype属性,这个属性是一个指针,指向一个对象(通过该构造函数创建实例对象的原型对象)。原型对象是包含特定类型的所有实例共享的属性和方法。原型对象的好处是,可以让所有实例对象共享它所包含的属性和方法。

        第一块中有提到,原型对象属于普通对象。Function.prototype是个例外,它是原型对象,却又是函数对象,作为一个函数对象,它又没有prototype属性。

其实原型对象就是构造函数的一个实例对象。person.prototype就是person的一个实例对象。相当于在person创建的时候,自动创建了一个它的实例,并且把这个实例赋值给了prototype。

原型链是实现继承的主要方法。

先说一下继承,许多OO语言都支持两张继承方式:接口继承、实现继承。

|- 接口继承:只继承方法签名

|- 实现继承:继承实际的方法

由于函数没有签名,在ECMAScript中无法实现接口继承,只支持实现继承,而实现继承主要是依靠原型链来实现

原型链基本思路:

利用原型让一个引用类型继承另一个引用类型的属性和方法。

每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数想指针(constructor),而实例对象都包含一个指向原型对象的内部指针(__proto__)。如果让原型对象等于另一个类型的实例,此时的原型对象将包含一个指向另一个原型的指针(__proto__),另一个原型也包含着一个指向另一个构造函数的指针(constructor)。假如另一个原型又是另一个类型的实例……这就构成了实例与原型的链条。


用原型链如何实现继承

。。。

要过滤掉对象继承的属性,用hasOwnProperty()来实现


相关文章

网友评论

      本文标题:JS考核将要问题摘要

      本文链接:https://www.haomeiwen.com/subject/itqbtqtx.html