JS学习中遇到的坑

JS学习中的坑

1、未经定义的变量就使用就会报错,但是在”typeof”里面唯一不报错,显示的是“undefined”

var x = 1;
if(function f(){}){
    x += typeof f;
 }
 console.log(x);//打印 1undefined
 **一旦变量未经定义就使用,肯定会报错;但是唯一不报错的就是放在typeof 里面 并且返回的是undefined;**
    typeof x;--> "string"

2、让函数打印出0-9 的数字

function test(){
    var arr = [];
    for(var i = 0; i < 10; i++){
        arr[i] = function(){
            console.log(i);
        }
     }
     return arr;
}
var myArr = test();
for(var j = 0; j < 10; j++){
    myArr[j]();
}  

结果是打印出十个10;
因为函数不是在console.log()的时候就打印出来,是把函数保存在外面,形成十个产生闭包的函数,十个函数共用一个作用域,并且访问的时候都是 10,这是一对十的方法,思路就是让他变成一对一的方式。

正确的做法是”利用立即执行函数”

实现的就是在执行到(function(j){}(i))这个函数的时候就“变现”

function test(){
    var arr= [];
    for(var i = 0; i < 10; i++){
        (function(j){//立即执行函数
            arr[j] = function(){
                console.log(j);
             }
          }(i))
    }
      return arr;
    }

    var myArr = test();
    for(var j = 0; j < 10;j++){
        myArr[j]();
    }

3、*!!!原始值不能有属性值和方法,能访问是隐式发生 new String(‘abcd’).length之后销毁

var str = "abcd";
str.length = 2;//系统执行之后就销毁
console.log(str);-->结果打印的是 abcd

典型题目

var str = "abc";
str += 1;//string 类型
var test = typeof(str);//test == "string"
if(test == 6) {
   test.sign = "typeof 的返回结果可能是 String";
}
console.log(test.sign);-->undefined

4、形参实参相映射,牵一发而动全身

下面alert的结果是什么

function arguments(a,b,c){
  test[2] = 10;
  alert(c);//打印结果为 10
}
arguments(1,2,4);

如果函数体改为下面,结果又会是什么?

c = 10;
alert(test[2]); //结果也是 10

5、原型的误区

    Person.prototype.name = 'rainy';
    function Person(){
        // var this ={__proto__:Person.prototype}
    }
    var person = new Person();
    Person.prototype.name = 'vita';
    console.log(person.__proto__name);//打印的就是 'vita'

下面的例子先new对象再来改变属性* new 对象之前改变属性不一样*

    Person.prototype.name = 'rainy';
    function Person(){}
    var person = new Person();
    Person.prototype = {
        name:'vita'
    }
    console.log(person.__proto__name);//打印的却是'rainy'?


    Person.prototype.name = 'rainy';
    function Person(){}

    Person.prototype = {
        name:'vita'
    }
    var person = new Person();
    console.log(person.__proto__name);//打印的却是'vita'?

基础例子

  var  obj.prototype = {name:'a'}
  var obj1 = obj;//打印 a
  obj.prototype = {name:'b'}

稍微难一点的问题

//这里有个小知识

sayName 里面的this 指向是,谁调用的这个方法,this就指向谁

Person.prototype = {
    name:'c',
    sayName:function(){
        console.log(this.name);
    }
}

function Person(){
    this.name = 'b';
    }
var person = new Person();
console.log(person.name);//打印的是 b

对象

**!!!!绝大多数对象最终都会继承自Object.prototype;
例外的是 Object.create(null);**

笔试题目

逗号运算符

var f = (
      function f(){
          return "1";
      },
      function g(){
         return 2;
      }
 )();

typeof f;//"number"
f;  // 打印出2

undefined 在typeof就可以用

   var x = 1;

    if(function f(){}){
    x +=typeof f;
    }

    x;//打印"1undefined"

基础知识点

undefined == null //true;
{}=={} //false
var obj = {};
var obj1 = obj;
    obj1 ==obj;//true;
    obj1 ===obj; //true 比对的是指向的地址

弄懂this 的指向

var name = '222';
var aa = {
    name:'111',
    say:function(){
        console.log(this.name)
    }
}

var fun = aa.say;

fun(); //this-->window
aa.say();//this-->aa; 打印的是111

var b = {
    name:'333',
    say:function(fun){
      console.log(this);//指向的是b;
      fun();//实际上就是把aa.say函数放在这里,没人调用他 this--->window
    }
}
b.say(aa.say); //222
b.say = aa.say(); //111

arguments.callee用处 指向函数的引用

在立即执行函数计算阶乘的时候的只能用

var num = (function(n){
     if(n==1){
        return 1;
    }
    return n * arguments.callee(n-1);
}(10));

num; //3628800

arguments 下面只有callee 跟length;caller指向的是函数被调用的环境

例如下面的例子

    function call(){
     console.log(arguments.callee);//指向的是call
        function test(){
             console.log(arguments.callee);
            }
        test();//指向的是test
    }
    call();

    function test(){
            demo();
    }
    function demo(){
        console.log(demo.caller);
    }
    test();  // 打印的结果是test(){demo();} caller指向的是调用它的环境 是test();在'use strict'模式下caller 会报错

下面打印的结果是什么;

    var foo =123;
    function print(){
        this.foo = 234;
        console.log(foo);
    }
    print();// 234 this--->window

  var foo =123;
    function print(){
        //var this = Object.create(print.prototype)
        this.foo = 234;
        console.log(foo);
    }
    new print();// 123 访问的foo 不是this.foo

2、使用test() 和new test()打印下面的结果分别是

    var a = 5;
    function test(){
        a = 0;
        console.log(a); //-->0
       console.log(this.a); //-->5 this 指向的是window
        var a;
        console.log(a); //-->0
    }

    test();
    new test(); //分别是 0 undefined 0 

    分析test()
         AO{
            a:undefined;-->0
            this:window;--->5
            }

3、判断传入的参数是不是NaN类型

function myIsNaN(num){
  var ret = Number(num);
    ret +="";
    if(ret =="NaN"){
        return true;
    }else {
        return false;
    }
}

4、print()();第一个括号返回的是函数,第二个括号返回的是结果

Var obj = {a:"002"}
function print(){
    obj.a = "a";
    Object.prototype.b = "b";
    return function inner(){
            console.log(obj.a);//a
            console.log(obj.b);//b
    }
}
print()();

5、浅层实现克隆obj 对象到obj1,obj1改变obj也改

        var obj = {
            name:"a",
            sex:"male"
        }

        var obj1 ={}

        function clone(origin,target){
            var target = target||{};//防止用户不传参数,就自己定义一个空对象
            for(prop in origin){
                target[prop] = origin[prop];
            }
             return target;//如果没传target就要把target return 出去
        }

    clone(obj,obj1);
    obj1;//{name: "a", sex: "male"}

6、深度拷贝

var obj = {
            name:"a",
            sex:"male",
            card:['visa','master'],
            wife:{
                name:"bcd",
                son:{
                    name:"aa"
                }
            }
        }

   var obj1 = {}

function deepClone(origin,target){
    //思路:遍历对象 for(var prop in obj)
            1、判断是不是原始值 typeof() 不是object
            2、判断是数组还是对象 (3种方法instanceof toSring(建议用这种) constructor)
            3、建立相应的数组或对象
            递归

    var a = {
        name:'vita',
        age:23,
        card:['master','visa'],
        wife:{
            name:'haha',
            son:{
                name:'a'
            }
        }
    };
    var b = {};
    function deepClone(origin, target){
        var target = target || {},
              toStr = Object.prototype.toString,
              arrStr = '[object Array]';
         for(var prop in origin){
            if(origin.hasOwnProperty(prop)){//要origin本身具有的属性,不是继承来的
                      if(typeof(origin[prop]) !=="null" &&typeof(origin[prop])== "object"){//判断形参是否是原始值,
                            if(toStr.call(origin[prop])==arrStr){
                                target[prop] = [];
                            }else {
                                target[prop] = {};
                        }
                        deepClone(origin[prop],target[prop]);

                      }else {
                target[prop] = origin[prop];
            }
          } 
       } 
       return target;
  }
  测试:a.card.push('lo');//["master", "visa", "lo"]
  b.card;  // ["master", "visa"]
 这就实现了改变a 不会改变b 的拷贝

类数组对象

阿里巴巴笔试题

var obj = {
        "2":"a",
        "3":"b",
        "length":2,
        "push":Array.prototype.push
}
obj.push('c');
obj.push('d');
//打印的结果是 
 obj = {2: "d", 3: "b", length: 2, push: ƒ}

要明白push 的内部原理

Array.prototype.push = function(target){
    obj[obj.length] = target;//obj[索引] = target;
    obj.length++;
}

6、执行下面

     var h = function a(){
            return 23;
    }
    typeof a();
    报错 a is no deifined 在这里 函数名a可以省略

猜你喜欢

转载自blog.csdn.net/Ultraman_and_monster/article/details/80872766