前端面试准备(一)

主要看了js笔试题

1

var name='狗蛋'
    function fn(){
        (function(){
            this.name = '小明'
        }).call(window)
    }
    fn.prototype.creat = function(){
        this.name ='小红兵'
    }
    console.log(new new fn().creat().name)

答案是 ‘小红兵
new一个方法为对象
new 对象会出错
new fn()对象
new fn().creat 方法
new new fn().creat() 对象,this指向本身,所以不用理fn里的call指向window
new this指向该对象

fn
ƒ fn(){
        (function(){
            this.name = '小明'
        }).call(window)
    }
new fn
fn {}__proto__: Object

new fn()
fn {}__proto__: Object


new fn.creat()
报错
VM2609:1 Uncaught TypeError: fn.creat is not a constructor
    at <anonymous>:1:1
(anonymous) @ VM2609:1

new fn().creat()
undefined

new fn().creat
ƒ (){
        this.name ='小红兵'
    }
new fn().creat().name
VM2668:1 Uncaught TypeError: Cannot read property 'name' of undefined
    at <anonymous>:1:17
(anonymous) @ VM2668:1fn

2

var name = 'lili';
    (function(){
        if(name === 'lili'){
            var name = 'yy';
            console.log('Bye'+ name)
        }else{
            console.log('bye'+name);
        }
    })()
    
    答案是byeundefined
    var name(lili) var name(yy)
    name = 'lili' name(yy)被覆盖了
    然后函数作用域
    会变量提升,则 var name 为undefined

预解析,变量提升

js文件执行2次,第一次是检查语法错误
第二次是2)编译性错误

var变量提升 任何作用域会触发一次预解析

先提升var 再提升函数

// console.log(number); 
ƒ number(){
        console.log('ss');
    }
    
//变量提升number,number()

     var number = 10;
    function number(){
        console.log('ss');
    }
    
    // console.log(number);  
    赋值只有等于号才能赋值 10

3

//定时器执行语句放到最后执行

for(var i = 0; i< 3; i++){
    setTimeout(()=>{
        console.log(i)
    },0)
}
//结果是3,3,3.
```
for(var i = 0; i< 3; i++){
    (function(x){
        setTimeout(()=>{
            console.log(x)
        },0)
    })(i)
}
```

//结果是0,1,2
//立即执行函数把i传给x
//i =0时,x = 0,所以定时器输出x= 0

for(var i = 0; i< 3; i++){
    (function(x){
        setTimeout(()=>{
            console.log(i)
        },0)
    })(i)
}
//定时器输出i,即是,3,3,3

js基本数据类型

Number,String(字符串) Boolean(布尔型) ,Null,
Undefined
引用数据类型 Object

ES6新增Symbol

本质上是一种唯一标识符,可用作对象的唯一属性名,这样其他人就不会改写或覆盖你设置的属性值。
声明方法:

let id = Symbol("id“);
Typeof检测的数据类型

对这5种数据类型会返回下面的值(以字符串形式显示)
undefined ---------- 如果值未定义 Undefined

boolean ---------- 如果这个值是布尔值 Boolean

string ---------- 如果这个值是字符串 String

number ---------- 如果这个值是数值类型 Number

扫描二维码关注公众号,回复: 5173102 查看本文章

object null---------- 如果这个值是对象或null Object

需要注意的是typeof null返回为object,因为特殊值null被认为是一个空的对象引用。

typeof(null)
"object"

注意对symbol来讲


typeof(Symbol)
"function"

覆盖默认的toString方法

var a = [1,2,3]
a.toString()
'1,2,3'
var d = new Array();
d.toString()
""
var o = new Object();
o.toString()
"[object Object]"

可以自定义一个方法来取代默认的 toString() 方法。该 toString() 方法不能传入参数并且必须返回一个字符串。自定义的 toString() 方法可以是任何我们需要的值,但如果它附带有关对象的信息,它将变的非常有用。

以下代码定义了Dog对象类型,并创建了一个Dog类型的theDog对象:

function Dog(name,breed,color,sex) {
   this.name=name;
   this.breed=breed;
   this.color=color;
   this.sex=sex;
}

var theDog = new Dog("Gabby","Lab","chocolate","female");

如果当前的对象调用了 toString() 方法,它将会返回从Object继承下来的 toString()方法的返回默认值:

theDog.toString(); // returns [object Object]

下面的代码中定义了一个叫做 dogToString() 的方法来覆盖默认的 toString() 方法。这个方法生成一个 "property = value;" 形式的字符串,该字符串包含了当前对象的 name, breed,color 和 sex 的值。

Dog.prototype.toString = function dogToString() {
  var ret = "Dog " + this.name + " is a " + this.sex + " " + this.color + " " + this.breed;
  return ret;
}

使用上述代码,任何时候在字符串上下文中使用theDog.toString(),JavaScript 都会自动调用 dogToString() 方法(dogToString()可以是一个匿名函数),并且返回以下字符串:

"Dog Gabby is a female chocolate Lab"

使用toString()检测对象类型

可以通过toString() 来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为thisArg。

var toString = Object.prototype.toString;

toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]

//Since JavaScript 1.8.5
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]

面试题

定义一个 log 方法,让它可以代理 console.log 方法,常见的解决方法是:

function log(msg) {
  console.log(msg);
}
log(1);    //1
log(1,2);    //1

上面方法可以解决最基本的需求,但是当传入参数的个数是不确定的时候,上面的方法就失效了,这个时候就可以考虑使用 apply 或者 call,注意这里传入多少个参数是不确定的,所以使用apply(传入的参数是数组)是最好的,方法如下:

function log(){
  console.log.apply(console, arguments);
};
log(1);    //1
log(1,2);    //1 2

接下来的要求是给每一个 log 消息添加一个"(app)"的前辍,比如:

log("hello world"); //(app)hello world

该怎么做比较优雅呢?这个时候需要想到arguments参数是个伪数组,通过 Array.prototype.slice.call 转化为标准数组,再使用数组方法unshift,像这样:

function log(){
  var args = Array.prototype.slice.call(arguments);
  args.unshift('(app)');
 
  console.log.apply(console, args);
};

Call,apply, bind

为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向。

javascript中的call和apply作用基本一样,应用某一对象的一个方法,用另一个对象替换当前对象,可将一个函数的对象上下文从初始的上下文改变为第一个传入的实参指定的新对象。区别在第二个参数,call()函数是将对象的参数==一个个==分别传入,apply()函数是将对象的参数以一个==数组==或arguments对象的形式整体传入。


function a(e,f){this.b=function(){console.log(e+f)}};

function c(){};

//call

a.call(c,2,3)

c.b()//输出"5";

//apply

a.apply(c,[2,3]);

c.b();//输出"5";

获取数组中的最大值和最小值

var  numbers = [5, 458 , 120 , -215 ]; 
var maxInNumbers = Math.max.apply(Math, numbers),   //458
    maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458

number 本身没有 max 方法,但是 Math 有,我们就可以借助 call 或者 apply 使用其方法。

什么是伪数组

当然它也是对象,伪数组一般具有以下特点:

按索引方式存储数据;
具有length属性;
没有数组的push、shift、pop等方法;(即不能修改长度)
var e = function(name, age){
this.name = name; this.age = age; 
this.say = arguments}; 

var f = new e(a,b);

f.age
(5) [1, 3, 8, 7, 4]
f.say
Arguments(2) [Array(3), Array(5), callee: ƒ, Symbol(Symbol.iterator): ƒ]
0: (3) [1, 3, 4]
1: (5) [1, 3, 8, 7, 4]
callee: ƒ (name, age)
length: 2
f.arguments

function的arguments对象,还有getElementsByTagName、ele.childNodes等返回的NodeList对象,或者自定义的某些对象,这些都可以是伪数组。

(function() {
  console.log(typeof arguments); // 输出 object,它并不是一个数组
}());

另外在DOM对象中,childNodes也是伪数组

console.log(typeof document.body.childNodes); // 输出 object

伪数组存在的意义,是可以让普通的对象也能正常使用数组的很多算法,比如:

var arr = Array.prototype.slice.call(arguments)

将arguments对象转换成一个真正的数组

但问题在于这个arguments对象其实并不是Array,所以没有slice方法。Array.prototype.slice.call( )可以间接对其实现slice的效果,而且返回的结果是真正的Array。

我们可以通过以下几种方式将伪数组转换为标准数组:

1、使用Array.prototype.slice.call()或[].slice.call();

Array.prototype.slice.call({  
 0:"hello",  
 1:12,  
 2:true,  
 length:3  
});  
//["hello", 12, true] 

slice() 方法可从已有的数组中返回选定的元素。

语法
arrayObject.slice(start,end)
返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。
您可使用负值从数组的尾部选取元素。

注释:如果 end 未被规定,那么 slice() 方法会选取从 start 到数组结尾的所有元素

2、使用ES6中Array.from方法;

Array.from({  
 0:"hello",  
 1:12,  
 2:2013,  
 3:"大学",  
 length:4  
});  
//["hello", 12, 2013, "大学"]  

猜你喜欢

转载自www.cnblogs.com/chaimi/p/10387442.html