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: "c", 3: "d", length: 4, 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可以省略

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值