三目运算符
判断?表达式:表达式
var str = '89'>'9'?'you are right':'you wrong';//字符串比较大小会从左到右一位一位比较。console.log(str);//you are wrong;
浅拷贝
var person = {name:'张三',age:10,sex:'male',height:180,weight:120}var person2 = {};for(var k in person){person2[k]= person[k];}console.log(person,person2)//此时是浅拷贝,虽然值都拷贝过来了。如果person里有一个数组或者对象。//那么修改person2的值,person的值也会发生改变。因为person2复制过来的是引用地址。
Object.prototype.num = 1;var person = {name:'张三',age:10,sex:'male',bro:{first:'张一',second:'张er'}}var person2 ={};for(var k in person){person2[k] = person[k];//此时因为bro这个属性是对象,bro里存着的是这个对象的引用地址.}person2.bro.third = '李四';console.log(person ,person2);
深拷贝
// hasOwnProperty 自身有该属性则返回true 否则返回false;function deepClone(origin, target) {var tar = target || {},//如果不传target就赋值为{};toStr = Object.prototype.toString,arrType = '[object Array]';for (var k in origin) {//遍历if (origin.hasOwnProperty(k)) {//是否是自身属性if (typeof origin[k] === 'object' && origin[k] != null) {//是对象且不是nullif (toStr.call(origin[k]) === arrType) {//是否是数组tar[k] = [];} else {tar[k] = {};}deepClone(origin[k], tar[k]);//如果是这样。递归实现} else {tar[k] = origin[k];//原始值。直接赋值。}}}return tar;}/*** 1 判断是否自身有这个属性 hasOwnProperty* 2 有 就判断这个属性值是否是对象(需要排除null) 是就判断是数组还是 对象。* 3 是数组或者对象都要 调用自身。* 4 返回tar*/var person = {name: '123',age: 122,son: {name: 'lucy',son: {name:'John'}},cars: ['Mazda', 'Benz'],eat:function () {console.log('i am eating an apple');}}var person2 = deepClone(person);person2.eat = function () {console.log('i am eating an orange');}person2.cars.push('XiaoPeng');console.log(person,person2);
笔试题
题目一
/*** AO {* foo:undefined->2* }**/function test(){console.log(foo);//undefinedvar foo = 2;console.log(foo);//2console.log(a);//a 并未在作用域内申明 a.is not defined}test();
题目二
var name = '222';var a = {name: '111',say:function () {console.log(this);console.log(this.name);}}var fun = a.say;fun();//222 将a.say 赋值给fun fun在全局。this指向window.a.say();//111 对象中调用this 指向该对象。var b = {name: '333',say:function (fun) {fun();}}b.say(a.say);//222 此时相当于 b.say(function(){console.log(this);console.log(this.name)});相当于fun 变量。b.say = a.say;//将a.say赋值给b.say;b.say();//333 对象中调用this this指向该对象。
题目三
function test() {var marty = {name: 'marty',print:function () {console.log(this.name);}}var test1 = {name: 'test1'}var test2 = {name:'test2'}var test3 = {name:'test3'}test3.print = marty.print;marty.print.call(test1);//test1 this的指向改变成了 test1marty.print.apply(test2);//test2 this的指向改变成了test2marty.print();//martytest3.print();//test3 this的指向改变成了test3}test();
题目四
var bar = {a:'1'}function test() {bar.a = 'a';Object.prototype.b = 'b';//函数终极原型链 breturn function () {console.log(bar.a);console.log(bar.b);}/*** 相当于 声明了一个函数。并且将这个函数return 出去。此时形成了闭包*/}test()();
作业
function Foo() {getName = function () {console.log(1);}return this;//构造函数会隐式返回this 如果不是构造函数这个this 指向就是window}//给Foo函数新增一个静态属性。Function也是对象。类似于var obj = {}; obj.getName = function(){.....}Foo.getName = function () {console.log(2);}//Foo原型上添加一个getName属性Foo.prototype.getName = function () {console.log(3);}//函数表达式var getName = function (params) {console.log(4);}//函数申明function getName(params) {console.log(5)}//对象调用自身的方法Foo.getName();//2//全局调用 因为函数声明提前了。函数表达式又把函数重新赋值getName();//4//()的优先级比.高 Foo()执行的时候把getName 重新赋值了。Foo().getName();//1// .的优先级比new高所以先执行Foo.getName();->new 2 new 一个数字没有含义。new Foo.getName();//2// new+一个函数()这个组合。new Foo()返回一个新的实例化对象。实例化对象没有getName().所以就往原型上找.new Foo().getName();//3//相当于new (new Foo()).getName(); new this.getName()//原型链上找getName; new 3是没有意义的。new new Foo().getName();// 3
