克隆/拷贝/复制
- 它们是同个东西
- 拷贝对象/克隆对象
浅拷贝
- 只拷贝对象表层的属性,引用值还是指向同个地址
- 修改引用值会相互影响
var person1 = {
name:'张三'
}
function clone(origin, target){
var tar = target || {};
for(var key in origin){
if(origin.hasOwnProperty(key)){
tar[key] = origin[key];
}
}
return tar;
}
深拷贝的常用方法:
1.原生递归遍历拷贝
2.用JSON对象转换的方法来拷贝, 缺点是不能拷贝方法。
var str = JSON.stringfy(obj);
var obj2 = JSON.parse(str);
3.jQuery的方法
深拷贝实现
- 向下递归拷贝,完全拷贝出一个新的对象
var person1 = {
name:'张三',
children:{
first:{
name:'张小一',
age:18
},
second:{
name:'张小二',
age:17
}
}
}
//深拷贝思路:
//首先遍历的时候剔除prototype上面的东西
//然后判断每项是不是引用值
//1. 用typeof判断,函数类型function可直接赋值
//2. 剔除null原始值打印为object的bug
//引用值下,判断是数组还是对象
//如果下层还有引用对象,赋值target[key]为数组或对象,递归调用拷贝函数,直到都为原始值
function deepClone(origin, target){
var target = target || {},
objStr = Object.prototype.toString,
arrType = '[object Array]';
for(var key in origin){
if(origin.hasOwnProperty(key)){
if(typeof(origin[key]) == 'object' && origin[key] != null){
if(objStr.call(origin[key]) === arrType){
target[key] = [];
}else{
target[key] = {};
}
deepClone(origin[key], target[key]);
}else{
target[key] = origin[key];
}
}
}
return target;
}
var person2 = deepClone(person1);
person2.children.third = {
name:'张小三',
age:16
};
console.log(person2);
console.log(person1);
对象属性遍历,this, caller, callee
链式操作:
sche.wakeup().morning().noon().afternoon();
实现:每个方法的最后 return this。
对象属性遍历:
obj.name //用.语法语法访问obj //实际上js引擎还是会给转成obj[‘name’]的形式,再访问
obj[‘name’] //用中括号可访问对象,属性名用字符串’’ //最早的JS引擎都是括号形式访问
字符串拼接的方式访问对象
obj[‘No’ + num] //访问形如No1, No2, No3此类的内容;
对象枚举方法:
数组遍历: for循环方法 //for(var i = 0; i < arr.length; i++){arr[i]}
(数组用for in 方法也可以)
对象遍历: for in 方法 //for(var key in obj){car[key]}
(for in 方法会遍历出原型链上的所有自定义属性,)
为什么for in里面,car.key访问不到?
car.key -> car[‘key’] -> 这个东西找不着,所以会返回undefined
判断是否是对象自身属性:只打印对象自身属性,排除原型链上属性的方法。一般使用obj.hasOwnProperty(key)来判断。
obj.hasOwnProperty(key) //方法返回true或false,放在if(xx)里面判断,返回true为自身的属性,才打印。
‘displacement’ in car
//返回true或false,隐式地找car[‘displacement’]存不存在
//前面一定要字符串括起来,直接写会报错
A instanceof B //判断A是否是B构造出来的
// 访问对象不存在的属性,返回的是undefiend
// 数组是特殊的对象,数组和对象都是引用值;
// 枚举就是有一组有共同特性的数据,就是枚举;在js中实际是对象
// 枚举 -> 遍历;遍历就是按顺序一个个获取信息的过程;
// JavaScript中,有枚举就一定有遍历;
三种判断数组的方法:
Object.prototype.toString.call(arr); //尽可能用这种方法判断
arr instanceof Array //是否数组构造方法构造出来的 //会有一些小问题
arr.constructor
微信qq等第三方接口返回错误信息的方式
完整的AO
this指向问题
//全局this指向window
//预编译函数this -> window //普通函数(没有return this的过程)
//apply/call改变了this的指向
//构造函数的this指向实例化对象
构造函数的AO
call/apply
callee/caller
arguments.callee - 返回当前函数本身 //返回正在执行的函数本身,在哪个函数里面返回哪个函数 // 它是实参列表上的一个属性
test2.caller - 返回调用当前函数的函数 //返回调用了test2的那个函数的函数体,这两个严格模式下会报错
立即执行函数调用自身 - arguments.callee
函数本身的属性.length - 形参长度
– 例子:用递归的方式累加n
笔试题
默认传参
bar.call() -> bar() -> bar.call(arguments) -> bar(arguments);
JS的typeof能够返回哪些值
number, boolean, string, object(null), undefined, function
NaN考题
NaN == NaN ?
写一个判断NaN的函数, 实现isNaN的功能;
判断那里要转为 res == 'NaN'
{} == {}? 为什么? 怎么相等?
不等于; 因为引用值对比的是地址;
引用值赋值,obj1 = obj;
浅拷贝,深拷贝,对象克隆,三目运算:
模块化开发作业
(团队协作开发)
模块化开发
window.onload = fucntion(){
init();
}
function init(){
initFb();
}
var initFb = (function(){
// 模块化 - 普通函数, return fun,initFb, init, onload,模块化直接用
function fb(n){
if(n <= 0){
return 0;
}
if(n <= 2){
return 1;
}
return fb(n - 1) + fb(n - 2);
}
return fb;
})();
插件开发
;(function(){
// 插件化 - 自启动,构造函数,原型,window, 插件要new一下用的
var Fb = function(){}
Fb.prototype.fb = function(n){
if(n <= 0){
return 0;
}
if(n <= 2){
return 1;
}
return arguments.callee(n - 1) + arguments.callee(n -2);
}
window抛出去
})();
三目运算
? : //每种语言都有
三种写法
一般:
a > 0 ? console.log('大于0') //;x 三目运算是一条语句,中间不能加分号
: console.log('小于0');
return写法:
str = a > 0 ? '大于0' //三目运算带有return 功能的
:'小于0'; //return
嵌套写法:
str = a > 0 ? (
a > 3 ? '大于3'
: '小于等于3'
)
: '小于等于0';
引用值的克隆/拷贝/复制 --真正的说法是叫克隆clone
指向同个存储空间的克隆 //引用值
var person1 = {name:'张三'};
var person2 = person1; //p1把存储地址的值给了p2,两者指向的是同个存储空间
person2.name = '李四';
// person1的值也会变成李四,因为
浅拷贝 //拷贝两个独立的对象,第一层属性互不影响
//但如果属性里有引用值,那么修改时还是会相互影响;
var person1 = {name:'张三'};
var person2 = {}
for(var key in person1){
person2[key] = person1[key];
}
//此时修改p2的属性值,p1不变;因为二者是不同的对象,只是把一层的属性和值拷贝以一份;
写个浅拷贝函数; -- 53min
深拷贝
写个深拷贝函数
function deepClone(origin, target){
var tar = target || {}, //做一下用户体验
toStr = Object.prototype.toString,
arrType = '[object Array]';
for(var key in origin){
if(origin.hasOwnProperty(key)){
if
}
}
}
用JSON方法来深拷贝,
缺点是不能拷贝方法
var p1 = {name:'张三'}
var str = JSON.stringify(p1); //先转成JSON字符串
var p2 = JSON.parse(str); //再把JSON字符串转成json对象
深拷贝有哪几种方法? - 3种
JQ深拷贝方法
JS原生递归的方法
JSON的方法
作业:(把答案写出来,并写上是什么原因)
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();
测试题:
用prompt接受用户输入年份
判断是否是闰年? 用三目运算来做;