JavaScript中的this问题汇总,以及浅层和深层克隆

例题一:下面能输出1,2,3,4,5的是

第一种:

function foo(){
		bar.apply(null,arguments);  //相当于直接调用bar(aguements);
	}
	function bar(){
		console.log(arguments);
	}
	foo(1,2,3,4,5);

控制台打印结果

第二种:可以执行打印

function foo(x){
		console.log(arguments);
		return x;
	}
	foo(1,2,3,4,5);

第三种:不报错,打印不了

function foo(x){
		console.log(arguments);
		return x;
	}(1,2,3,4,5);

第四种:可以执行

	(function foo(x){
		console.log(arguments);
		return x;
	})(1,2,3,4,5);       //立即执行函数

例题二:

	function b(x,y,a){
		arguments[2] = 10;
		alert(a);  //print 10  形参和实参相映射,但是本质上无关,如果将代码改变为a = 10; alert(arguments[2]);也会打印出10
	}

例题三:

 

   var f = (
        function f(){
            return "1";
        },
        function g(){
            return 2;
        }
        )();
console.log(typeof(f));   //print number,因为f是一个立即执行函数,实际执行的函数是逗号表达式的最后一个函数,也就是g()

例题四

	var x = 1;
	if (function f(){}) { //函数f被括号括起来被当做一个表达式,返回结果为true,但是代价就是f会被立即销毁,typeof f,就相当于typeof 字符串,返回结果是undefined所以x+=typeof f就是一个数字加一个字符串,直接连接,结果是1undefined
		x += typeof f;    
	}
	console.log(x);

例题五 判断题

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

结果

this指向详解

1.函数预编译过程this——>window

2.全局作用域里this——>window

3.call/apply可以改变函数运行时this指向

4.obj.func();func()里面的this指向obj

相关例题

var name = "222";
var a = {
	name : "111",
	say : function(){
		console.log(this.name);
	}
}
var fun = a.say;
fun();     //print 222,全局调用,this指向window
a.say();   //print 111,a调用函数say,this指向a
var b = {
	name : "333",
	say : function(fun){
		fun();
	}
}
b.say(a.say);   //print 222,a.say作为参数传进fun中,因为fun函数是直接调用的,不是某个对象调用,所以仍然是在全局调用,所以this还是指向window
b.say = a.say;  
b.say();        //print 333,b对象调用函数say,this指向b

arguments

arguments.callee

举例一

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

举例二

function test(){
	console.log(arguments.callee);     //argument.callee在哪个函数内,就打印的是哪个函数,print test()
	function demo(){
		console.log(arguments.callee);  //print demo()
	}
	demo();
}
test();

控制台打印结果

func.caller

function test(){
	demo();
}
function demo(){
	console.log(demo.caller); //caller是函数自带的一个属性,指代函数被调用的环境
}
test();

控制台打印结果

例题五

this指向问题

var foo = '123';
function print(){
	var foo = '456';
	this.foo = '789';   //这个this.foo指的是全局里的foo即把原来的foo = ‘123’ 修改为 foo = ‘789’
	console.log(foo);    //这个foo指的是print内部的foo,即Ao里面的,离得最近的,(如果打印的是this.foo,那么,结果是789,如果注视掉上一行,this.foo的结果是123)
}
print();     //print 456

例题六

执行test

var a = 5;
function test(){
	a = 0;
	alert(a);    //alert 0
	alert(this.a); //alert 5
	var a;
	alert(a);      //alert 0
}
test();

new test

var a = 5;
function test(){
	a = 0;
	alert(a);    //alert 0
	alert(this.a); //alert undefine
	var a;
	alert(a);      //alert 0
}
new test();  //new一个test,就是创建一个this对象,而这个对象上面是没有a的所以第二个打印的是undefined

例题七

function print(){
	console.log(foo);    //undefined
	var foo = 2;
	console.log(foo);    //2
	console.log(hello);  //报错,Uncaught ReferenceError: hello is not defined
}
print();

例题八

function print(){
	var marty = {
		name : "marty",
		printName : function(){console.log(this.name);}
	}

	var test1 = { name : "test1"};
	var test2 = { name : "test2"};
	var test3 = { name : "test3"};

	test3.printName = marty.printName;
	var printName2 = marty.printName.bind({name:123});
		
	marty.printName.call(test1);  //print test1
	marty.printName.apply(test2); //print test2
	marty.printName();   //print marty
	printName2();       //print 123
	test3.printName();  //print test3
}
print();

例题九

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

js深度克隆

js对象组成

说对象的深度克隆之前,要先明白js中对象的组成。以一句话说js中一切皆对象

具体数据类型分为两种:

-原始数据类型:其中存储的是对象的实际地址。eg number,string,boolean,还有两个特殊的null,undefined

-引用数据类型:其中存储的是对象的引用地址。eg  array ,function,object

克隆的概念

浅层克隆:原始类型为值传递,对象类型仍为引用传递。

深度克隆:所有元素或属性均完全复制,与原对象完全脱离,也就是说所有对于新对象的修改都不会反映到原对象。

例题十

浅层克隆,即原始值的克隆,克隆后的两个对象里面的东西互不影响,看下面控制台的打印结果

var obj ={
	name : 'abc',
	age : 123,
	sex : 'female'
}
var obj1 = {}
function clone(origin,target){
	var target = target || {};    //容错
	for(var prop in origin){
		target[prop] = origin[prop];
	}
	return target;
}
clone(obj,obj1);

深度克隆:如果对象中含有引用值,继续使用浅层克隆,引用值的修改会互相影响,深度克隆解决了这个问题

var obj = {
	name : "abc",
	age : 123,
	card : ['visa','master'],
	wife : {
		name : "bcd",
		son : {
			name : "aaa"
		}
	}
}
var obj1 = {}
function deepClone(origin,target){
	var target = target || {},
	toStr = Object.prototype.toString,
	arrStr = "[Object Array]";
    for(prop in origin){
		if(origin.hasOwnProperty(prop)){
			if(origin[prop] !== "null" && typeof(origin[prop]) == 'object'){
				if(toStr.call(origin[prop] == arrStr)){   //1
					target[prop] = [];                    //2
				}else{                                    //3
				target[prop] = {};                        //4
				}                                         //5
			deepClone(origin[prop],target[prop]);
		    }else{
		    	target[prop] = origin[prop];
		    }
		}
	}
	return target;
}
//1.判断是不是原始值     1.typeof() object instanceof toString constructor,instanceof在跨父子域的时候又问题,比如在子域建立的空数组【】instanceof父域的arry,返回是false,toString没有问题
//2.判断是数组还是对象
//3.建立相应的数组或对象

上述代码的1-5的标记行,还可以用三目运算符来简化一下如下

target[prop] = (toStr.call(origin[prop] == arrStr) ? [] : {};

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值