var person ={
gender: '男',
height: 185,
toShanhai: function(){
console.log('dodododood')
}
};
console.log(person.gender);
console.log(person['height'])
person.gender='manel';
person['height'] = 11;
delete preson.gender
person ={} //清空對象
person = null; //把person變量賦值為null 此後person不是對象
function Preson(age,gender){
this.age = age;
this.gender = gender;
}
var p1 = new Person(5,'lusi');
function fn(){
return [1,115,55];
}
var q = new fn(); //返回的是數組的類型 不是函數的實例
console.log(q instanceof fn); //false
構造函數的prototype 原型對象
通過構造函數是可以方便地構造自己想要的代碼 但是如果構造函數的方法功能都差不多 構造多了會造成内存的浪費 比如以下代碼
function Person(name,age){
this.name = name;
this.age = age;
this.say = function(){
console.log('hello')
}
}
var p1 = new Person();
var p2 = new Person();
console.log(p1.say===p2.say);//p1對象的say方法和p2對象say方法不是同一個方法會造成内存浪費
把功能相似的方法寫到原型中就是同一個方法
Person.prototype.run=function(){
console.log('hello');
}
console.log(p1.run===p2.run)//p1 p2 對象的 run方法是同一個方法
給原型對象添加方法的時候 會讓代碼產生 不少的冗餘如
Person.prototype.s1 = function(){}
Person.prototype.s2 = function(){}
改良方法
Person.prototype = {
a1: function(){
},
a2: function(){
}
}
這方法有個弊端會破壞原有的原型鏈 一般用於自定義的構造函數 用這種方法時必須先改變原型后創建對象 不然對象會按照之前的原型 造成訪問不了新的原型
var o3 = {gender:'男',grade:'初三'};
var o4 = {};
for(var key in o3){
o4[key] = o3[key];
}
//封裝成函數
function extend(source,target){
for(var key in source){
target[key] = source[key];
}
}
o5={};
extend(o3,o5);
function Animal(name,age,gender){
this.name = name;
this.age = age;
this.gender = gender;
}
function Person(name.age,gender,say){
Animal.apply(this,[name,age,gender]); //等價於 Animal.call(this,[name,age,gender])
this.say =say;
}
var p1 = new Person('tom',15,'man',function(){
console.log('hello world')
})
function fn(){
var age;
console.log(age); //undeinfed
age=18;
console.log(age);//18
}
function fn(){
var a = 4;
return function(){
a++;
console.log(a);
}
}
var f1 = fn(); //指向匿名函數
f1(); //5
f1(); //6
f1(); //7
var f2 = fn();
f2(); //5
f2(); //6
f2(); //7
var ktv = (function Ktv(){
//保護這些變量
var leastPrice =1000; // 最低消費金額
var total = 0; //消費合計金額
return {
buy: function(price){
total=+price;
},
pay: function(){
if(total<leastPrice){
console.log('最低消費未達到,請繼續購物');
}else{
console.log('歡迎下次光臨');
}
},
editLeast: function(id,price){
if(id=888){
leastPrice = price;
console.log('現在最低消費是'+price);
}else{
console.log('你沒有權限去修改');
}
}
}
})()
function f1(){
var a= 5;
return function(){
a++;
console.log(a);
}
}
var q1=f1();
//如果想釋放q1保存的a 只能把q1賦值為Null
q1=null;
//方法調用
var age = 18;
var p ={
age:15,
say:function(){
console.log(this.age);
}
}
var f1 = p.say;
f1(); //函數調用 内部this 指向windows 所以age為18
p.say(); //方法調用 内部this 指向對象
function fn(name){
this.name = name;
}
var n = new fn('xiaoming'); //構造函數 this 指向實例本身
function jQuery(){
var _init=jQuery.prototype.init;
//_init就是一个构造函数
return new _init();
}
jQuery.prototype={
constructor:jQuery,
length:100,
init:function(){
//this可以访问到实例本身的属性,也可以访问到init.prototype中的属性
//这里的init.prototype并不是jQuery.prototype
console.log(this.length);
//正确答案:undefined
//100? 错误的
}
}
//this指向init构造函数的实例
//-->1、首先查看本身有没有length属性
//-->2、如果本身没有该属性,那么去它的原型对象中查找
//-->3、如果原型对象中没有,那么就去原型对象的原型对象中查找,最终一直找到根对象(Object.prototype)
//-->4、最终都没有找到的话,我们认为该对象并没有该属性,如果获取该属性的值:undefined
//上下文调用方式,有3种,call、apply、bind
function f1(){
console.log(this);
}
//call方法的第一个参数决定了函数内部的this的值
f1.call([1,3,5])
f1.call({age:20,height:1000})
f1.call(1)
f1.call("abc")
f1.call(true);
f1.call(null)
f1.call(undefined);
//上述代码可以用apply完全替换
//总结:
//call方法的第一个参数:
//1、如果是一个对象类型,那么函数内部的this指向该对象
//2、如果是undefined、null,那么函数内部的this指向window
//3、如果是数字-->this:对应的Number构造函数的实例
// --> 1 --> new Number(1)
// 如果是字符串-->this:String构造函数的实例
// --> "abc" --> new String("abc")
// 如果是布尔值-->this:Boolean构造函数的实例
// --> false --> new Boolean(false)
//call和apply都可以改变函数内部的this的值
//不同的地方:传参的形式不同
function toString(a,b,c){
console.log(a+" "+b+" "+c);
}
toString.call(null,1,3,5) //"1 3 5"
toString.apply(null,[1,3,5])//"1 3 5"
var obj={
name:"西瓜",
drink:(function(){
//this指向了:{ name:"橙汁" }
console.log(this.name);
}).bind({ name:"橙汁" })
}
obj.drink();
//模板字符串就是一种字符串的新的表现形式
//a、基本用法
var s1 = ` hello `
var s2 = ' hello '
//b、模板字符串解决了一些痛点
//+字符串和变量拼接
var s3 =" a " + s1 + " b " + s2;
var s4 = ` a ${s1} b ${s2}`; //减少了错误几率
//+字符串换行
var s5 =`
123
${s2}
${s3}
${s1}
`;
console.log(s5);
function a({width,height}){
//let {width,height} = option
console.log(width);
console.log(height);
}
s={width:55,height:555};
a(s);
function fn(){
//arguments是函数内部的一个局部变量,
//arguments.length表示函数的实参的个数
console.log(arguments.length);
for(var i =0 ; i<arguments.length; i++){
console.log(arguments[i]);
}
}
fn(1,3,5) //3
// fn("a","b","c","d","e") //5
//es6箭头函数内部不能使用arguments
//为了弥补这个问题,rest参数应孕而生
//...args就是rest参数
//-->产生了一个变量,这个变量是一个数组,数组里面包含了这个函数调用时传递的所有实参
function q(...args){
//验证args是不是数组?
console.log(args instanceof Array);//true
console.log(Object.prototype.toString.call(args));//"[object Array]"
console.log(Array.isArray(args)); //true es5中的新方法
console.log(args);
}
q(1,3,5);
q(2,3,4,5,6,7,8);
//无参的匿名函数
div.onclick=function(){
}
//相当于:
div.onclick=()=>{
}
//有一个参数的匿名函数
// var fn=function(name){
// console.log(name);
// }
//等价于:
var fn=name=>{
console.log(name);
}
//也等价于:
// var fn=(name)=>{
// console.log(name);
// }
//有2个或以上的参数的匿名函数
// var q=function(name,age){
// }
//等价于
var q=(name,age)=>{
//切记:()不能省略
}
//有了匿名函数之后,我们的代码清晰了很多:
var students=[1,3,5];
students.forEach(function(value,index){
})
students.forEach((value,index)=>{
})
//只需要一个参数
students.forEach(value=>{
})
var p={
age:18,
//es6中对象方法的箭头函数表示形式
run:()=>{
setTimeout(()=>{
//this:window
console.log(this);//this是window
},100)
},
travel:function(){
//this:p
setTimeout(()=>{
console.log(this);//this是p
},100)
},
//推荐使用的方式☆☆☆:es6中对象方法的简写形式
say(){
console.log("say方法中的this:",this);
setTimeout(()=>{
console.log("say内部的延迟函数:",this);//this是p
},100)
},
}
p.run();
p.travel();
p.say();
var source ={
age:18,
height:170,
className:'1年二班'
}
// 對對象的淺拷貝
var newObj = Object.assign({},source);
console.log(newObj);
var newObj2={};
Object.assign(newObj2,source);
console.log(newObj2);
var car ={brand:'BMW',price:360000};
//對象的淺拷貝
var car2 ={ ...car };
//拷貝的同時 還可以修改某個值
var car3 = { ...car,price:222};
//拷貝的同時可以擴展一些屬性
var car4 = { ...car,type:'suv'};
//數組也可以拷貝
var s1=[1,3,5];
var s2 =[ ...s1];
function fn(){
return new Promise(resolve=>{
setTimeout(()=>{
console.log('你好');
//告訴外界 到這裏異步已經執行完畢
resolve();
},1000);
})
}
//等待 異步執行完畢后執行一下代碼 res參數是異步操作的函數返回值
fn().then(res=>{
//執行下一步
console.log('下一步');
fn().then(res=>{
console.log('執行第二步');
})
})
//執行順序 你好->下一步->你好->執行第二步
function fn(){
return new Promise(resolve=>{
setTimeout(() => {
console.log('第一步');
resolve();
}, 1000);
});
}
function fn2(){
return new Promise(resolve=>{
setTimeout(() => {
console.log('第二步');
resolve();
}, 1000);
});
}
//fn fn2 函數相互調用
fn().then(res=>{
return fn2();
}).then(res=>{
return fn();
}).then(res=>{
return fn2();
}).then(res=>{
setTimeout(() => {
console.log('完成');
}, 1000);
});
//執行順序 第一步->第二步->第一步->第二步->完成
var b = false;
function fn(){
//resolve 成功 reject失敗
return new Promise((resolve,reject)=>{
setTimeout(() => {
if(b){
var s= 1;
console.log('執行成功');
resolve(s);
}else{
var s=2;
console.log('執行失敗');
reject(s);
}
}, 1000);
});
}
fn().then(res=>{
console.log(`s的值是${res}`);
//處理錯誤的時候用catch
}).catch(reserr=>{
console.log(`s的值${reserr}`);
})
//執行結果 執行失敗 ->s的值是 2