1.立即执行函数 return 与 window的区别
1.window写法new Foo.getName
;(function(){var Test = function(){console.log('123');}Test.prototype = {}window.Test = Test;})();Test();Test()只执行时执行一次
2.return 写法
var Test = (function(){var Test = function(){console.log('345');}return Test;})();Test();Test() 执行两次
2.三目运算
var str = 89>9 ? ('89'>'9'?'通过了':'内层未通过'): '外层未通过';console.log(str);
3.浅拷贝: 浅拷贝就是将对象中的所有元素复制到新的对象中
浅拷贝对于原始值类型与引用类型的方式有区别
1.原始值类型字段的值被复制到副本中后,在副本中的修改不会影响源对象对应的值
2.引用类型的字段被复制到副本中的却是引用类型的引用,而不是引用的对象
在副本中对子元素引用类型的字段值被修改后,源对象的值也将被修改。
Object.prototype.num = 1;var person1 = {name:'张三',age:18,sex:'male',height:180,weight:140,son:{first:'Jenney',second:'Lucy',Third:'Jone'},children:{first:{name:'张小一',age:13},second:{name:'张小二',age:14},third:{name:'张小三',age:15},},car:['Benz','Mazda']}var person2 = {};for(var key in person1){person2[key] = person1[key];}person2.name = '李四';person2.son.forth = 'Ben';console.log(person1,person2);//此方法原型链上的属性也会复制到新对象中 num:1
浅拷贝封装函数 排查原型链上继承的属性
Object.prototype.num = 1;var person1 = {name:'张三',age:18,sex:'male',height:180,weight:140,son:{first:'Jenney',second:'Lucy',Third:'Jone'},children:{first:{name:'张小一',age:13},second:{name:'张小二',age:14},third:{name:'张小三',age:15},},car:['Benz','Mazda']}var person2 = clone(person1);function clone(origin,target){var target = target || {}for(var key in origin){//筛选origin对象自身的属性if(origin.hasOwnProperty(key))target[key] = origin[key];}return target;}person2.name = '李四';person2.son.forth = 'Ben';console.log(person1,person2);//副本更改源数据也会更改
4.深拷贝
深拷贝和上面浅拷贝不同,就是彻底copy一个对象,而不是copy对象的引用。
方法一: 原生写法
Object.prototype.num = 1;
var person1 = {
name:'张三',
age:18,
sex:'male',
height:180,
weight:140,
son:{
first:'Jenney',
second:'Lucy',
Third:'Jone'
},
children:{
first:{
name:'张小一',
age:13
},
second:{
name:'张小二',
age:14
},
third:{
name:'张小三',
age:15
},
},
car:['Benz','Mazda']
}
var person2 = deepClone(person1);
person2.name = '李四';
person2.children.forth = {
name:'张小四',
age:1
};
person2.car.push('BYD');
console.log(person1,person2);
function deepClone(origin,target){
var target = target || {},
toStr = Object.prototype.toString,
arrType = '[object Array]';
for(var key in origin){
if(origin.hasOwnProperty(key)){
if(typeof(origin[key]) === 'object' && origin[key] !== null){ // 先测是否是引用型 typeof([]) 等于 object
// if(toStr.call(origin[key]) === arrType){
// target[key] = [];
// }else{
// target[key] = {};
// }
target[key] = toStr.call(origin[key]) === arrType ? [] : {};
deepClone(origin[key],target[key]); //递归执行
}else{
target[key] = origin[key];
}
}
}
return target;
}
方法二:通过JSON方法 弊端不能拷贝对象里的方法
Object.prototype.num = 1;
var person1 = {
name:'张三',
age:18,
sex:'male',
height:180,
weight:140,
son:{
first:'Jenney',
second:'Lucy',
Third:'Jone'
},
children:{
first:{
name:'张小一',
age:13
},
second:{
name:'张小二',
age:14
},
third:{
name:'张小三',
age:15
},
},
car:['Benz','Mazda']
}
var str = JSON.stringify(person1);
var person2 = JSON.parse(str);
person2.name = '李四';
person2.children.forth = {
name:'张小四',
age:1
};
person2.car.push('BYD');
console.log(person1,person2);
习题
1
function test(){
console.log(foo); //undefined
var foo = 2;
console.log(foo); //2
console.log(a); //报错
}
test();
2.
function a(){
var test;
test();
function test(){
console.log(1); //1
}
}
a();
// AO = {
// test: undefined => test(){}
// }
3.
var name = '222'
var a ={
name :'111',
say:function(){
console.log(this.name);
}
}
var fun = a.say;
fun(); // 2222
a.say(); // 111
var b = {
name:'333',
say:function(fun){
fun();
}
}
b.say(a.say); // 2222
b.say = a.say;
b.say()// 333
4.
function test(){
var marty = {
name:'marty',
printName:function(){
console.log(this.name);
}
}
var test1 = {
name: 'test1'
}
var test2 = {
name: 'test2'
}
var test3 = {
name:'test3',
printName:function(){
console.log(this.name);
}
}
test3.printName = marty.printName;
marty.printName.call(test1); // test1 this的指向被改成 test1
marty.printName.apply(test2); // test2 this的指向被改成 test2
marty.printName(); //marty
test3.printName(); //test3
}
test();
5.
var bar = {
a:'1'
};
function test(){
bar.a = 'a';
Object.prototype.b='b';
return function inner(){
console.log(bar.a); // a
console.log(bar.b); // b 自身没有的属性去上级寻找
}
}
console.log(test());
test()();
课后作业
1.写出代码的执行结果跟步骤
function Foo(){
getName = function(){
console.log(1);
}
return this;
}
Foo.getName = function(){
console.log(2);
}
Foo.prototype.getName = function(){
console.log(3);
}
var getName = function(){
console.log(4);
}
function getName(){
console.log(5);
}
Foo.getName();
getName();
Foo().getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName()
解析: Foo.getName();
函数也是特殊的对象 所以 Foo.getName() 等价于=> 执行 function Foo(){} 这个函数对象下面的getName属性 Foo.getName = function(){
console.log(2);
}
所以输出2
getName();
GO:{
getName: 1.undefined => 2. function getName(){ 3.赋值操作 var getName = function(){
console.log(5); console.log(4);
} }
}
所以输出4;
Foo().getName();
执行 function Foo(){ 因为 getName 没有 var 所以变量提升到全局
getName = function(){
console.log(1);
}
return this;
}
所以 GO:{
getName: 1.undefined => 2. function getName(){ => 3.赋值操作 var getName = function(){
console.log(5); console.log(4);
} }
4. getName = function(){
console.log(1);
}
}
所以输出1
getName();
GO:{
getName: 1.undefined => 2. function getName(){ => 3.赋值操作 var getName = function(){
console.log(5); console.log(4);
} }
4. getName = function(){
console.log(1);
}
}
所以还是输出1
new Foo.getName();
. 跟 new 先运行 . 所以 先运行 Foo.getName = function(){ 输出 2 然后 => new 2
console.log(2);
}
所以还是输出2
new Foo().getName();
new Foo() 跟 . 先执行 new Foo() => 然后执行 this.getName() 本身没有 => 原型 Foo.prototype.getName = function(){
console.log(3);
}
所以输出 3
new new Foo().getName();
new Foo() 跟 . 先执行 new Foo() => 然后执行 this.getName() 本身没有 => 原型 Foo.prototype.getName = function(){
console.log(3);
}
再 new 3
所以还是输出 3
知识点
运算符优先级:
2. 请用 window.prompt 接收用户输入的年份 判断是否是闰年 用三目运算
var year = window.prompt('请输入判断的年份');
function isLeapYear(year){
return (year % 4 ===0 && year % 100!=0)||(year%400===0)?'是闰年':'不是闰年';
}
console.log(isLeapYear(year));

